Browse Source

`default:` to `case:`; `no_alias` to `#no_alias`

Ginger Bill 8 years ago
parent
commit
45dbe8d354
18 changed files with 240 additions and 1612 deletions
  1. 1 1
      code/demo.odin
  2. 16 16
      core/fmt.odin
  3. 10 0
      core/os.odin
  4. 2 2
      core/os_windows.odin
  5. 4 4
      core/strconv.odin
  6. 1 1
      core/utf16.odin
  7. 0 65
      src/check_decl.c
  8. 2 21
      src/check_expr.c
  9. 4 13
      src/check_stmt.c
  10. 35 18
      src/checker.c
  11. 16 9
      src/entity.c
  12. 54 55
      src/ir.c
  13. 15 15
      src/ir_print.c
  14. 0 1305
      src/old_vm.c
  15. 51 55
      src/parser.c
  16. 27 27
      src/ssa.c
  17. 0 3
      src/tokenizer.c
  18. 2 2
      src/types.c

+ 1 - 1
code/demo.odin

@@ -10,7 +10,7 @@ main :: proc() {
 		case '-': accumulator -= 1;
 		case '-': accumulator -= 1;
 		case '*': accumulator *= 2;
 		case '*': accumulator *= 2;
 		case '/': accumulator /= 2;
 		case '/': accumulator /= 2;
-		default: // Ignore everything else
+		case: // Ignore everything else
 		}
 		}
 	}
 	}
 
 

+ 16 - 16
core/fmt.odin

@@ -189,7 +189,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 		match {
 		match {
 		case ti == type_info(int):  write_string(buf, "int");
 		case ti == type_info(int):  write_string(buf, "int");
 		case ti == type_info(uint): write_string(buf, "uint");
 		case ti == type_info(uint): write_string(buf, "uint");
-		default:
+		case:
 			write_string(buf, info.signed ? "i" : "u");
 			write_string(buf, info.signed ? "i" : "u");
 			fi := Fmt_Info{buf = buf};
 			fi := Fmt_Info{buf = buf};
 			fmt_int(&fi, u64(8*info.size), false, 64, 'd');
 			fmt_int(&fi, u64(8*info.size), false, 64, 'd');
@@ -440,7 +440,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
 		case u16:  num = int(i);
 		case u16:  num = int(i);
 		case u32:  num = int(i);
 		case u32:  num = int(i);
 		case u64:  num = int(i);
 		case u64:  num = int(i);
-		default:
+		case:
 			ok = false;
 			ok = false;
 		}
 		}
 	}
 	}
@@ -468,7 +468,7 @@ fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) {
 	match verb {
 	match verb {
 	case 't', 'v':
 	case 't', 'v':
 		write_string(buf, b ? "true" : "false");
 		write_string(buf, b ? "true" : "false");
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 	}
 	}
 }
 }
@@ -515,7 +515,7 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned
 			neg = i < 0;
 			neg = i < 0;
 			if neg { i = -i; }
 			if neg { i = -i; }
 			u = u64(i);
 			u = u64(i);
-		default:
+		case:
 			panic("is_integer_negative: Unknown integer size");
 			panic("is_integer_negative: Unknown integer size");
 		}
 		}
 	}
 	}
@@ -555,7 +555,7 @@ _write_int :: proc(fi: ^Fmt_Info, u: u64, base: int, is_signed: bool, bit_size:
 	match base {
 	match base {
 	case 2, 8, 10, 12, 16:
 	case 2, 8, 10, 12, 16:
 		break;
 		break;
-	default:
+	case:
 		panic("_write_int: unknown base, whoops");
 		panic("_write_int: unknown base, whoops");
 	}
 	}
 
 
@@ -598,7 +598,7 @@ fmt_int :: proc(fi: ^Fmt_Info, u: u64, is_signed: bool, bit_size: int, verb: run
 			_write_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
 			_write_int(fi, u, 16, false, bit_size, __DIGITS_UPPER);
 		}
 		}
 
 
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 	}
 	}
 }
 }
@@ -659,7 +659,7 @@ fmt_float :: proc(fi: ^Fmt_Info, v: f64, bit_size: int, verb: rune) {
 			_pad(fi, str[1..]);
 			_pad(fi, str[1..]);
 		}
 		}
 
 
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
 	}
 	}
@@ -681,7 +681,7 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
 			_write_int(fi, u64(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
 			_write_int(fi, u64(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
 		}
 		}
 
 
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 	}
 	}
 }
 }
@@ -690,7 +690,7 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
 	match verb {
 	match verb {
 	case 'p', 'v':
 	case 'p', 'v':
 		// Okay
 		// Okay
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
 	}
 	}
@@ -709,7 +709,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 
 
 	using Type_Info;
 	using Type_Info;
 	match e in v.type_info {
 	match e in v.type_info {
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
 	case Enum:
 	case Enum:
@@ -760,7 +760,7 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			if !ok {
 			if !ok {
 				write_string(fi.buf, "!%(BAD ENUM VALUE)");
 				write_string(fi.buf, "!%(BAD ENUM VALUE)");
 			}
 			}
-		default:
+		case:
 			fmt_bad_verb(fi, verb);
 			fmt_bad_verb(fi, verb);
 			return;
 			return;
 		}
 		}
@@ -796,7 +796,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			}
 			}
 			write_byte(fi.buf, '}');
 			write_byte(fi.buf, '}');
 
 
-		default:
+		case:
 			fmt_value(fi, any{v.data, info.base}, verb);
 			fmt_value(fi, any{v.data, info.base}, verb);
 		}
 		}
 
 
@@ -956,7 +956,7 @@ fmt_complex :: proc(fi: ^Fmt_Info, c: complex128, bits: int, verb: rune) {
 		fmt_float(fi, i, bits/2, verb);
 		fmt_float(fi, i, bits/2, verb);
 		write_rune(fi.buf, 'i');
 		write_rune(fi.buf, 'i');
 
 
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
 	}
 	}
@@ -983,7 +983,7 @@ fmt_quaternion :: proc(fi: ^Fmt_Info, c: quaternion256, bits: int, verb: rune) {
 		fmt_float(fi, k, bits/4, verb);
 		fmt_float(fi, k, bits/4, verb);
 		write_rune(fi.buf, 'k');
 		write_rune(fi.buf, 'k');
 
 
-	default:
+	case:
 		fmt_bad_verb(fi, verb);
 		fmt_bad_verb(fi, verb);
 		return;
 		return;
 	}
 	}
@@ -1029,7 +1029,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 	case u32:     fmt_int(fi, u64(a), false, 32, verb);
 	case u32:     fmt_int(fi, u64(a), false, 32, verb);
 	case u64:     fmt_int(fi, u64(a), false, 64, verb);
 	case u64:     fmt_int(fi, u64(a), false, 64, verb);
 	case string:  fmt_string(fi, a, verb);
 	case string:  fmt_string(fi, a, verb);
-	default:      fmt_value(fi, arg, verb);
+	case:      fmt_value(fi, arg, verb);
 	}
 	}
 
 
 }
 }
@@ -1102,7 +1102,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ..any) -> string {
 				fi.hash = true;
 				fi.hash = true;
 			case '0':
 			case '0':
 				fi.zero = !fi.minus;
 				fi.zero = !fi.minus;
-			default:
+			case:
 				break prefix_loop;
 				break prefix_loop;
 			}
 			}
 		}
 		}

+ 10 - 0
core/os.odin

@@ -35,3 +35,13 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
 	return data[0..<bytes_read], true;
 	return data[0..<bytes_read], true;
 }
 }
 
 
+write_entire_file :: proc(name: string, data: []byte) -> bool {
+	fd, err := open(name, O_WRONLY, 0);
+	if err != 0 {
+		return false;
+	}
+	defer close(fd);
+
+	bytes_written, write_err := write(fd, data);
+	return write_err != 0;
+}

+ 2 - 2
core/os_windows.odin

@@ -89,7 +89,7 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
 		create_mode = win32.OPEN_ALWAYS;
 		create_mode = win32.OPEN_ALWAYS;
 	case mode&O_TRUNC == O_TRUNC:
 	case mode&O_TRUNC == O_TRUNC:
 		create_mode = win32.TRUNCATE_EXISTING;
 		create_mode = win32.TRUNCATE_EXISTING;
-	default:
+	case:
 		create_mode = win32.OPEN_EXISTING;
 		create_mode = win32.OPEN_EXISTING;
 	}
 	}
 
 
@@ -314,7 +314,7 @@ _alloc_command_line_arguments :: proc() -> []string {
 				j += 2;
 				j += 2;
 			case 0xdc00 <= str[j] && str[j] < 0xe000:
 			case 0xdc00 <= str[j] && str[j] < 0xe000:
 				return "";
 				return "";
-			default:
+			case:
 				if i+3 > len {
 				if i+3 > len {
 					return "";
 					return "";
 				}
 				}

+ 4 - 4
core/strconv.odin

@@ -108,7 +108,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
 	case 64:
 	case 64:
 		bits = transmute(u64, val);
 		bits = transmute(u64, val);
 		flt = &f64_info;
 		flt = &f64_info;
-	default:
+	case:
 		panic("strconv: invalid bit_size");
 		panic("strconv: invalid bit_size");
 	}
 	}
 
 
@@ -132,7 +132,7 @@ generic_ftoa :: proc(buf: []byte, val: f64, fmt: byte, prec, bit_size: int) -> [
 	case 0: // denormalized
 	case 0: // denormalized
 		exp++;
 		exp++;
 
 
-	default:
+	case:
 		mant |= u64(1) << flt.mantbits;
 		mant |= u64(1) << flt.mantbits;
 	}
 	}
 
 
@@ -312,7 +312,7 @@ is_integer_negative :: proc(u: u64, is_signed: bool, bit_size: int) -> (unsigned
 			neg = i < 0;
 			neg = i < 0;
 			if neg { i = -i; }
 			if neg { i = -i; }
 			u = u64(i);
 			u = u64(i);
-		default:
+		case:
 			panic("is_integer_negative: Unknown integer size");
 			panic("is_integer_negative: Unknown integer size");
 		}
 		}
 	}
 	}
@@ -356,7 +356,7 @@ append_bits :: proc(buf: []byte, u: u64, base: int, is_signed: bool, bit_size: i
 		case 10: i--; a[i] = 'd';
 		case 10: i--; a[i] = 'd';
 		case 12: i--; a[i] = 'z';
 		case 12: i--; a[i] = 'z';
 		case 16: i--; a[i] = 'x';
 		case 16: i--; a[i] = 'x';
-		default: ok = false;
+		case: ok = false;
 		}
 		}
 		if ok {
 		if ok {
 			i--;
 			i--;

+ 1 - 1
core/utf16.odin

@@ -50,7 +50,7 @@ encode :: proc(d: []u16, s: []rune) {
 			d[n+1]  = u16(r2);
 			d[n+1]  = u16(r2);
 			n += 2;
 			n += 2;
 
 
-		default:
+		case:
 			d[n] = u16(REPLACEMENT_CHAR);
 			d[n] = u16(REPLACEMENT_CHAR);
 			n++;
 			n++;
 		}
 		}

+ 0 - 65
src/check_decl.c

@@ -417,68 +417,6 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
 	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 	check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
 }
 }
 
 
-
-void check_alias_decl(Checker *c, Entity *e, AstNode *expr, Type *named_type) {
-	GB_ASSERT(e->type == NULL);
-	GB_ASSERT(e->kind == Entity_Alias);
-
-	if (e->flags & EntityFlag_Visited) {
-		e->type = t_invalid;
-		return;
-	}
-	e->flags |= EntityFlag_Visited;
-	e->type = t_invalid;
-
-	expr = unparen_expr(expr);
-
-	if (expr->kind == AstNode_Alias) {
-		error_node(expr, "#alias of an #alias is not allowed");
-		return;
-	}
-
-	Operand operand = {0};
-	check_expr_or_type(c, &operand, expr);
-	if (operand.mode != Addressing_Type) {
-		error_node(expr, "#alias declarations only allow types");
-		return;
-	}
-	e->kind = Entity_TypeName;
-	e->TypeName.is_type_alias = true;
-	e->type = NULL;
-
-	DeclInfo *d = c->context.decl;
-	d->type_expr = expr;
-	check_type_decl(c, e, d->type_expr, named_type);
-
-
-	// Operand o = {0};
-	// Entity *f = NULL;
-	// if (expr->kind == AstNode_Ident) {
-	// 	f = check_ident(c, &o, expr, NULL, NULL, true);
-	// } else if (expr->kind == AstNode_SelectorExpr) {
-	// 	f = check_selector(c, &o, expr, NULL);
-	// } else {
-	// 	check_expr_or_type(c, &o, expr);
-	// }
-	// if (o.mode == Addressing_Invalid) {
-	// 	return;
-	// }
-	// switch (o.mode) {
-	// case Addressing_Type:
-	// 	e->type = o.type;
-	// 	// e->kind = Entity_TypeName;
-	// 	// e->TypeName.is_type_alias = true;
-	// 	e->Alias.kind     = EntityAlias_Type;
-	// 	e->Alias.original = f;
-	// 	break;
-	// default:
-	// 	error_node(expr, "#alias declarations only allow types");
-	// 	e->kind = Entity_Invalid;
-	// 	e->type = t_invalid;
-	// 	break;
-	// }
-}
-
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 	if (e->type != NULL) {
 	if (e->type != NULL) {
 		return;
 		return;
@@ -513,9 +451,6 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
 	case Entity_TypeName:
 	case Entity_TypeName:
 		check_type_decl(c, e, d->type_expr, named_type);
 		check_type_decl(c, e, d->type_expr, named_type);
 		break;
 		break;
-	case Entity_Alias:
-		check_alias_decl(c, e, d->init_expr, named_type);
-		break;
 	case Entity_Procedure:
 	case Entity_Procedure:
 		check_proc_lit(c, e, d);
 		check_proc_lit(c, e, d);
 		break;
 		break;

+ 2 - 21
src/check_expr.c

@@ -1313,8 +1313,8 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 		}
 		}
 		break;
 		break;
 
 
+	case Entity_TypeAlias:
 	case Entity_TypeName:
 	case Entity_TypeName:
-		// NOTE(bill): Cyclical dependency checking is handled in the "type system" not here
 		o->mode = Addressing_Type;
 		o->mode = Addressing_Type;
 		break;
 		break;
 
 
@@ -1344,17 +1344,6 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *
 		o->mode = Addressing_Value;
 		o->mode = Addressing_Value;
 		break;
 		break;
 
 
-	case Entity_Alias: {
-		// error_node(n, "#alias entities are not yet supported");
-		// TODO(bill): Fix Entity_Alias rules
-		if (e->Alias.kind == EntityAlias_Type) {
-			o->mode = Addressing_Type;
-		} else {
-			o->mode = Addressing_Invalid;
-			return e;
-		}
-	} break;
-
 	default:
 	default:
 		compiler_error("Unknown EntityKind");
 		compiler_error("Unknown EntityKind");
 		break;
 		break;
@@ -3070,10 +3059,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 		expr_entity = e;
 		expr_entity = e;
 
 
 		Entity *original_e = e;
 		Entity *original_e = e;
-		while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) {
-			e = e->Alias.original;
-		}
-
 		if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) {
 		if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) {
 			// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
 			// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
 			// It pretty much needs to be in this order and this way
 			// It pretty much needs to be in this order and this way
@@ -3295,6 +3280,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 			operand->mode = Addressing_Value;
 			operand->mode = Addressing_Value;
 		}
 		}
 		break;
 		break;
+	case Entity_TypeAlias:
 	case Entity_TypeName:
 	case Entity_TypeName:
 		operand->mode = Addressing_Type;
 		operand->mode = Addressing_Type;
 		break;
 		break;
@@ -3306,11 +3292,6 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
 		operand->builtin_id = entity->Builtin.id;
 		operand->builtin_id = entity->Builtin.id;
 		break;
 		break;
 
 
-	case Entity_Alias: {
-		error_node(selector, "#alias entities are not yet supported");
-		return NULL;
-	} break;
-
 	// NOTE(bill): These cases should never be hit but are here for sanity reasons
 	// NOTE(bill): These cases should never be hit but are here for sanity reasons
 	case Entity_Nil:
 	case Entity_Nil:
 		operand->mode = Addressing_Value;
 		operand->mode = Addressing_Value;

+ 4 - 13
src/check_stmt.c

@@ -262,10 +262,10 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
 		AstNode *ln = unparen_expr(lhs_node);
 		AstNode *ln = unparen_expr(lhs_node);
 		if (ln->kind == AstNode_IndexExpr) {
 		if (ln->kind == AstNode_IndexExpr) {
 			AstNode *x = ln->IndexExpr.expr;
 			AstNode *x = ln->IndexExpr.expr;
-			TypeAndValue *tav = type_and_value_of_expression(&c->info, x);
-			GB_ASSERT(tav != NULL);
-			if (tav->mode != Addressing_Variable) {
-				if (!is_type_pointer(tav->type)) {
+			TypeAndValue tav = type_and_value_of_expr(&c->info, x);
+			GB_ASSERT(tav.mode != Addressing_Invalid);
+			if (tav.mode != Addressing_Variable) {
+				if (!is_type_pointer(tav.type)) {
 					gbString str = expr_to_string(lhs.expr);
 					gbString str = expr_to_string(lhs.expr);
 					error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str);
 					error_node(lhs.expr, "Cannot assign to the value of a map `%s`", str);
 					gb_string_free(str);
 					gb_string_free(str);
@@ -443,15 +443,6 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
 	add_entity_use(c, expr, e);
 	add_entity_use(c, expr, e);
 
 
 	switch (e->kind) {
 	switch (e->kind) {
-	case Entity_Alias: {
-		if (e->Alias.original != NULL) {
-			check_using_stmt_entity(c, us, expr, is_selector, e->Alias.original);
-		} else {
-			error(us->token, "`using` cannot be applied to the alias `%.*s`", LIT(e->token.string));
-			return false;
-		}
-	} break;
-
 	case Entity_TypeName: {
 	case Entity_TypeName: {
 		Type *t = base_type(e->type);
 		Type *t = base_type(e->type);
 		if (is_type_union(t)) {
 		if (is_type_union(t)) {

+ 35 - 18
src/checker.c

@@ -28,8 +28,8 @@ typedef enum BuiltinProcId {
 	BuiltinProc_cap,
 	BuiltinProc_cap,
 
 
 	BuiltinProc_new,
 	BuiltinProc_new,
-	BuiltinProc_free,
 	BuiltinProc_make,
 	BuiltinProc_make,
+	BuiltinProc_free,
 
 
 	BuiltinProc_reserve,
 	BuiltinProc_reserve,
 	BuiltinProc_clear,
 	BuiltinProc_clear,
@@ -82,8 +82,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
 	{STR_LIT("cap"),              1, false, Expr_Expr},
 	{STR_LIT("cap"),              1, false, Expr_Expr},
 
 
 	{STR_LIT("new"),              1, false, Expr_Expr},
 	{STR_LIT("new"),              1, false, Expr_Expr},
-	{STR_LIT("free"),             1, false, Expr_Stmt},
 	{STR_LIT("make"),             1, true,  Expr_Expr},
 	{STR_LIT("make"),             1, true,  Expr_Expr},
+	{STR_LIT("free"),             1, false, Expr_Stmt},
 
 
 	{STR_LIT("reserve"),          2, false, Expr_Stmt},
 	{STR_LIT("reserve"),          2, false, Expr_Stmt},
 	{STR_LIT("clear"),            1, false, Expr_Stmt},
 	{STR_LIT("clear"),            1, false, Expr_Stmt},
@@ -624,14 +624,15 @@ void add_declaration_dependency(Checker *c, Entity *e) {
 }
 }
 
 
 
 
-void add_global_entity(Entity *entity) {
+Entity *add_global_entity(Entity *entity) {
 	String name = entity->token.string;
 	String name = entity->token.string;
 	if (gb_memchr(name.text, ' ', name.len)) {
 	if (gb_memchr(name.text, ' ', name.len)) {
-		return; // NOTE(bill): `untyped thing`
+		return entity; // NOTE(bill): `untyped thing`
 	}
 	}
 	if (scope_insert_entity(universal_scope, entity)) {
 	if (scope_insert_entity(universal_scope, entity)) {
 		compiler_error("double declaration");
 		compiler_error("double declaration");
 	}
 	}
+	return entity;
 }
 }
 
 
 void add_global_constant(gbAllocator a, String name, Type *type, ExactValue value) {
 void add_global_constant(gbAllocator a, String name, Type *type, ExactValue value) {
@@ -646,6 +647,11 @@ void add_global_string_constant(gbAllocator a, String name, String value) {
 
 
 }
 }
 
 
+Type *add_global_type_alias(gbAllocator a, String name, Type *t) {
+	Entity *e = add_global_entity(make_entity_type_alias(a, NULL, make_token_ident(name), t));
+	return e->type;
+}
+
 
 
 void init_universal_scope(void) {
 void init_universal_scope(void) {
 	BuildContext *bc = &build_context;
 	BuildContext *bc = &build_context;
@@ -657,9 +663,16 @@ void init_universal_scope(void) {
 	for (isize i = 0; i < gb_count_of(basic_types); i++) {
 	for (isize i = 0; i < gb_count_of(basic_types); i++) {
 		add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_types[i].Basic.name), &basic_types[i]));
 		add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_types[i].Basic.name), &basic_types[i]));
 	}
 	}
+#if 1
 	for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) {
 	for (isize i = 0; i < gb_count_of(basic_type_aliases); i++) {
 		add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_type_aliases[i].Basic.name), &basic_type_aliases[i]));
 		add_global_entity(make_entity_type_name(a, NULL, make_token_ident(basic_type_aliases[i].Basic.name), &basic_type_aliases[i]));
 	}
 	}
+#else
+	{
+		t_byte = add_global_type_alias(a, str_lit("byte"), &basic_types[Basic_u8]);
+		t_rune = add_global_type_alias(a, str_lit("rune"), &basic_types[Basic_i32]);
+	}
+#endif
 
 
 // Constants
 // Constants
 	add_global_constant(a, str_lit("true"),  t_untyped_bool, exact_value_bool(true));
 	add_global_constant(a, str_lit("true"),  t_untyped_bool, exact_value_bool(true));
@@ -786,11 +799,6 @@ void destroy_checker(Checker *c) {
 }
 }
 
 
 
 
-TypeAndValue *type_and_value_of_expression(CheckerInfo *i, AstNode *expression) {
-	TypeAndValue *found = map_tav_get(&i->types, hash_pointer(expression));
-	return found;
-}
-
 
 
 Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
 Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
 	if (identifier->kind == AstNode_Ident) {
 	if (identifier->kind == AstNode_Ident) {
@@ -806,13 +814,22 @@ Entity *entity_of_ident(CheckerInfo *i, AstNode *identifier) {
 	return NULL;
 	return NULL;
 }
 }
 
 
-Type *type_of_expr(CheckerInfo *i, AstNode *expression) {
-	TypeAndValue *found = type_and_value_of_expression(i, expression);
-	if (found) {
-		return found->type;
+
+TypeAndValue type_and_value_of_expr(CheckerInfo *i, AstNode *expression) {
+	TypeAndValue result = {0};
+	TypeAndValue *found = map_tav_get(&i->types, hash_pointer(expression));
+	if (found) result = *found;
+	return result;
+}
+
+
+Type *type_of_expr(CheckerInfo *i, AstNode *expr) {
+	TypeAndValue tav = type_and_value_of_expr(i, expr);
+	if (tav.mode != Addressing_Invalid) {
+		return tav.type;
 	}
 	}
-	if (expression->kind == AstNode_Ident) {
-		Entity *entity = entity_of_ident(i, expression);
+	if (expr->kind == AstNode_Ident) {
+		Entity *entity = entity_of_ident(i, expr);
 		if (entity) {
 		if (entity) {
 			return entity->type;
 			return entity->type;
 		}
 		}
@@ -2102,6 +2119,7 @@ void check_parsed_files(Checker *c) {
 	// TODO(bill): Any other checks?
 	// TODO(bill): Any other checks?
 
 
 
 
+#if 1
 	// Add "Basic" type information
 	// Add "Basic" type information
 	for (isize i = 0; i < gb_count_of(basic_types)-1; i++) {
 	for (isize i = 0; i < gb_count_of(basic_types)-1; i++) {
 		Type *t = &basic_types[i];
 		Type *t = &basic_types[i];
@@ -2116,14 +2134,13 @@ void check_parsed_files(Checker *c) {
 			add_type_info_type(c, t);
 			add_type_info_type(c, t);
 		}
 		}
 	}
 	}
-
+#endif
 
 
 
 
 	// NOTE(bill): Check for illegal cyclic type declarations
 	// NOTE(bill): Check for illegal cyclic type declarations
 	for_array(i, c->info.definitions.entries) {
 	for_array(i, c->info.definitions.entries) {
 		Entity *e = c->info.definitions.entries.e[i].value;
 		Entity *e = c->info.definitions.entries.e[i].value;
-		if (e->kind == Entity_TypeName ||
-		    (e->kind == Entity_Alias && e->Alias.kind == EntityAlias_Type)) {
+		if (e->kind == Entity_TypeName) {
 			if (e->type != NULL) {
 			if (e->type != NULL) {
 				// i64 size  = type_size_of(c->sizes, c->allocator, e->type);
 				// i64 size  = type_size_of(c->sizes, c->allocator, e->type);
 				i64 align = type_align_of(c->allocator, e->type);
 				i64 align = type_align_of(c->allocator, e->type);

+ 16 - 9
src/entity.c

@@ -14,7 +14,8 @@ typedef struct DeclInfo DeclInfo;
 	ENTITY_KIND(Builtin) \
 	ENTITY_KIND(Builtin) \
 	ENTITY_KIND(ImportName) \
 	ENTITY_KIND(ImportName) \
 	ENTITY_KIND(LibraryName) \
 	ENTITY_KIND(LibraryName) \
-	ENTITY_KIND(Alias) \
+	ENTITY_KIND(TypeAlias) \
+	ENTITY_KIND(ProcedureAlias) \
 	ENTITY_KIND(Nil) \
 	ENTITY_KIND(Nil) \
 	ENTITY_KIND(Label)
 	ENTITY_KIND(Label)
 
 
@@ -109,10 +110,10 @@ struct Entity {
 			String name;
 			String name;
 			bool   used;
 			bool   used;
 		} LibraryName;
 		} LibraryName;
+		i32 TypeAlias;
 		struct {
 		struct {
-			EntityAliasKind kind;
-			Entity *        original;
-		} Alias;
+			Entity *original;
+		} ProcedureAlias;
 		i32 Nil;
 		i32 Nil;
 		struct {
 		struct {
 			String name;
 			String name;
@@ -243,13 +244,19 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type
 	return entity;
 	return entity;
 }
 }
 
 
-Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type,
-                          EntityAliasKind kind, Entity *original) {
-	Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type);
-	entity->Alias.kind     = kind;
-	entity->Alias.original = original;
+Entity *make_entity_type_alias(gbAllocator a, Scope *scope, Token token, Type *type) {
+	Entity *entity = alloc_entity(a, Entity_TypeAlias, scope, token, type);
 	return entity;
 	return entity;
 }
 }
+Entity *make_entity_procedure_alias(gbAllocator a, Scope *scope, Token token, Entity *original) {
+	GB_ASSERT(original != NULL);
+	Entity *entity = alloc_entity(a, Entity_ProcedureAlias, scope, token, original->type);
+	entity->ProcedureAlias.original = original;
+	return entity;
+}
+
+
+
 
 
 Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
 Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
 	Token token = make_token_ident(name);
 	Token token = make_token_ident(name);

+ 54 - 55
src/ir.c

@@ -3570,23 +3570,23 @@ bool is_double_pointer(Type *t) {
 irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	expr = unparen_expr(expr);
 	expr = unparen_expr(expr);
 
 
-	TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(expr));
-	GB_ASSERT_NOT_NULL(tv);
+	TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
+	GB_ASSERT(tv.mode != Addressing_Invalid);
 
 
-	if (tv->value.kind != ExactValue_Invalid) {
+	if (tv.value.kind != ExactValue_Invalid) {
 		// NOTE(bill): Edge case
 		// NOTE(bill): Edge case
-		if (tv->value.kind != ExactValue_Compound &&
-		    is_type_vector(tv->type)) {
-			Type *elem = base_vector_type(tv->type);
-			ExactValue value = convert_exact_value_for_type(tv->value, elem);
+		if (tv.value.kind != ExactValue_Compound &&
+		    is_type_vector(tv.type)) {
+			Type *elem = base_vector_type(tv.type);
+			ExactValue value = convert_exact_value_for_type(tv.value, elem);
 			irValue *x = ir_add_module_constant(proc->module, elem, value);
 			irValue *x = ir_add_module_constant(proc->module, elem, value);
-			return ir_emit_conv(proc, x, tv->type);
+			return ir_emit_conv(proc, x, tv.type);
 		}
 		}
 
 
-		return ir_add_module_constant(proc->module, tv->type, tv->value);
+		return ir_add_module_constant(proc->module, tv.type, tv.value);
 	}
 	}
 
 
-	if (tv->mode == Addressing_Variable) {
+	if (tv.mode == Addressing_Variable) {
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 	}
 	}
 
 
@@ -3614,7 +3614,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 			         LIT(token.pos.file), token.pos.line, token.pos.column);
 			         LIT(token.pos.file), token.pos.line, token.pos.column);
 			return NULL;
 			return NULL;
 		} else if (e->kind == Entity_Nil) {
 		} else if (e->kind == Entity_Nil) {
-			return ir_value_nil(proc->module->allocator, tv->type);
+			return ir_value_nil(proc->module->allocator, tv.type);
 		}
 		}
 
 
 		irValue **found = map_ir_value_get(&proc->module->values, hash_pointer(e));
 		irValue **found = map_ir_value_get(&proc->module->values, hash_pointer(e));
@@ -3644,8 +3644,8 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(se, SelectorExpr, expr);
 	case_ast_node(se, SelectorExpr, expr);
-		TypeAndValue *tav = map_tav_get(&proc->module->info->types, hash_pointer(expr));
-		GB_ASSERT(tav != NULL);
+		TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
+		GB_ASSERT(tav.mode != Addressing_Invalid);
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 		return ir_addr_load(proc, ir_build_addr(proc, expr));
 	case_end;
 	case_end;
 
 
@@ -3725,7 +3725,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 
 	case_ast_node(ta, TypeAssertion, expr);
 	case_ast_node(ta, TypeAssertion, expr);
 		TokenPos pos = ast_node_token(expr).pos;
 		TokenPos pos = ast_node_token(expr).pos;
-		Type *type = tv->type;
+		Type *type = tv.type;
 		irValue *e = ir_build_expr(proc, ta->expr);
 		irValue *e = ir_build_expr(proc, ta->expr);
 		Type *t = type_deref(ir_type(e));
 		Type *t = type_deref(ir_type(e));
 		if (is_type_union(t)) {
 		if (is_type_union(t)) {
@@ -3744,13 +3744,13 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 		case Token_And:
 		case Token_And:
 			return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
 			return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
 		default:
 		default:
-			return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv->type);
+			return ir_emit_unary_arith(proc, ue->op.kind, ir_build_expr(proc, ue->expr), tv.type);
 		}
 		}
 	case_end;
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, expr);
 	case_ast_node(be, BinaryExpr, expr);
 		irValue *left = ir_build_expr(proc, be->left);
 		irValue *left = ir_build_expr(proc, be->left);
-		Type *type = default_type(tv->type);
+		Type *type = default_type(tv.type);
 
 
 		switch (be->op.kind) {
 		switch (be->op.kind) {
 		case Token_Add:
 		case Token_Add:
@@ -3822,7 +3822,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 		if (map_tav_get(&proc->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
 		if (map_tav_get(&proc->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
 			GB_ASSERT(ce->args.count == 1);
 			GB_ASSERT(ce->args.count == 1);
 			irValue *x = ir_build_expr(proc, ce->args.e[0]);
 			irValue *x = ir_build_expr(proc, ce->args.e[0]);
-			irValue *y = ir_emit_conv(proc, x, tv->type);
+			irValue *y = ir_emit_conv(proc, x, tv.type);
 			return y;
 			return y;
 		}
 		}
 
 
@@ -3843,7 +3843,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 
 
 				case BuiltinProc_transmute: {
 				case BuiltinProc_transmute: {
 					irValue *x = ir_build_expr(proc, ce->args.e[1]);
 					irValue *x = ir_build_expr(proc, ce->args.e[1]);
-					return ir_emit_transmute(proc, x, tv->type);
+					return ir_emit_transmute(proc, x, tv.type);
 				}
 				}
 
 
 				case BuiltinProc_len: {
 				case BuiltinProc_len: {
@@ -4042,7 +4042,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					gbAllocator a = proc->module->allocator;
 					gbAllocator a = proc->module->allocator;
 
 
 					AstNode *node = ce->args.e[0];
 					AstNode *node = ce->args.e[0];
-					TypeAndValue tav = *type_and_value_of_expression(proc->module->info, node);
+					TypeAndValue tav = type_and_value_of_expr(proc->module->info, node);
 					Type *type = base_type(tav.type);
 					Type *type = base_type(tav.type);
 
 
 					if (is_type_dynamic_array(type)) {
 					if (is_type_dynamic_array(type)) {
@@ -4394,14 +4394,14 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 						return ir_addr_load(proc, vector_addr);
 						return ir_addr_load(proc, vector_addr);
 					}
 					}
 					irValue *src = vector_addr.addr;
 					irValue *src = vector_addr.addr;
-					irValue *dst = ir_add_local_generated(proc, tv->type);
+					irValue *dst = ir_add_local_generated(proc, tv.type);
 
 
 					for (i32 i = 1; i < ce->args.count; i++) {
 					for (i32 i = 1; i < ce->args.count; i++) {
-						TypeAndValue *tv = type_and_value_of_expression(proc->module->info, ce->args.e[i]);
-						GB_ASSERT(is_type_integer(tv->type));
-						GB_ASSERT(tv->value.kind == ExactValue_Integer);
+						TypeAndValue tv = type_and_value_of_expr(proc->module->info, ce->args.e[i]);
+						GB_ASSERT(is_type_integer(tv.type));
+						GB_ASSERT(tv.value.kind == ExactValue_Integer);
 
 
-						i32 src_index = cast(i32)tv->value.value_integer;
+						i32 src_index = cast(i32)tv.value.value_integer;
 						i32 dst_index = i-1;
 						i32 dst_index = i-1;
 
 
 						irValue *src_elem = ir_emit_array_epi(proc, src, src_index);
 						irValue *src_elem = ir_emit_array_epi(proc, src, src_index);
@@ -4418,9 +4418,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					ir_emit_comment(proc, str_lit("complex"));
 					ir_emit_comment(proc, str_lit("complex"));
 					irValue *real = ir_build_expr(proc, ce->args.e[0]);
 					irValue *real = ir_build_expr(proc, ce->args.e[0]);
 					irValue *imag = ir_build_expr(proc, ce->args.e[1]);
 					irValue *imag = ir_build_expr(proc, ce->args.e[1]);
-					irValue *dst = ir_add_local_generated(proc, tv->type);
+					irValue *dst = ir_add_local_generated(proc, tv.type);
 
 
-					Type *ft = base_complex_elem_type(tv->type);
+					Type *ft = base_complex_elem_type(tv.type);
 					real = ir_emit_conv(proc, real, ft);
 					real = ir_emit_conv(proc, real, ft);
 					imag = ir_emit_conv(proc, imag, ft);
 					imag = ir_emit_conv(proc, imag, ft);
 					ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), real);
 					ir_emit_store(proc, ir_emit_struct_ep(proc, dst, 0), real);
@@ -4435,9 +4435,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					irValue *imag = ir_build_expr(proc, ce->args.e[1]);
 					irValue *imag = ir_build_expr(proc, ce->args.e[1]);
 					irValue *jmag = ir_build_expr(proc, ce->args.e[2]);
 					irValue *jmag = ir_build_expr(proc, ce->args.e[2]);
 					irValue *kmag = ir_build_expr(proc, ce->args.e[3]);
 					irValue *kmag = ir_build_expr(proc, ce->args.e[3]);
-					irValue *dst = ir_add_local_generated(proc, tv->type);
+					irValue *dst = ir_add_local_generated(proc, tv.type);
 
 
-					Type *ft = base_quaternion_elem_type(tv->type);
+					Type *ft = base_quaternion_elem_type(tv.type);
 					real = ir_emit_conv(proc, real, ft);
 					real = ir_emit_conv(proc, real, ft);
 					imag = ir_emit_conv(proc, imag, ft);
 					imag = ir_emit_conv(proc, imag, ft);
 					jmag = ir_emit_conv(proc, jmag, ft);
 					jmag = ir_emit_conv(proc, jmag, ft);
@@ -4454,25 +4454,25 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					ir_emit_comment(proc, str_lit("real"));
 					ir_emit_comment(proc, str_lit("real"));
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *real = ir_emit_struct_ev(proc, val, 0);
 					irValue *real = ir_emit_struct_ev(proc, val, 0);
-					return ir_emit_conv(proc, real, tv->type);
+					return ir_emit_conv(proc, real, tv.type);
 				} break;
 				} break;
 				case BuiltinProc_imag: {
 				case BuiltinProc_imag: {
 					ir_emit_comment(proc, str_lit("imag"));
 					ir_emit_comment(proc, str_lit("imag"));
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *imag = ir_emit_struct_ev(proc, val, 1);
 					irValue *imag = ir_emit_struct_ev(proc, val, 1);
-					return ir_emit_conv(proc, imag, tv->type);
+					return ir_emit_conv(proc, imag, tv.type);
 				} break;
 				} break;
 				case BuiltinProc_jmag: {
 				case BuiltinProc_jmag: {
 					ir_emit_comment(proc, str_lit("jmag"));
 					ir_emit_comment(proc, str_lit("jmag"));
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *jmag = ir_emit_struct_ev(proc, val, 2);
 					irValue *jmag = ir_emit_struct_ev(proc, val, 2);
-					return ir_emit_conv(proc, jmag, tv->type);
+					return ir_emit_conv(proc, jmag, tv.type);
 				} break;
 				} break;
 				case BuiltinProc_kmag: {
 				case BuiltinProc_kmag: {
 					ir_emit_comment(proc, str_lit("kmag"));
 					ir_emit_comment(proc, str_lit("kmag"));
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *val = ir_build_expr(proc, ce->args.e[0]);
 					irValue *kmag = ir_emit_struct_ev(proc, val, 3);
 					irValue *kmag = ir_emit_struct_ev(proc, val, 3);
-					return ir_emit_conv(proc, kmag, tv->type);
+					return ir_emit_conv(proc, kmag, tv.type);
 				} break;
 				} break;
 
 
 				case BuiltinProc_conj: {
 				case BuiltinProc_conj: {
@@ -4481,14 +4481,14 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					irValue *res = NULL;
 					irValue *res = NULL;
 					Type *t = ir_type(val);
 					Type *t = ir_type(val);
 					if (is_type_complex(t)) {
 					if (is_type_complex(t)) {
-						res = ir_add_local_generated(proc, tv->type);
+						res = ir_add_local_generated(proc, tv.type);
 						irValue *real = ir_emit_struct_ev(proc, val, 0);
 						irValue *real = ir_emit_struct_ev(proc, val, 0);
 						irValue *imag = ir_emit_struct_ev(proc, val, 1);
 						irValue *imag = ir_emit_struct_ev(proc, val, 1);
 						imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
 						imag = ir_emit_unary_arith(proc, Token_Sub, imag, ir_type(imag));
 						ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
 						ir_emit_store(proc, ir_emit_struct_ep(proc, res, 0), real);
 						ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
 						ir_emit_store(proc, ir_emit_struct_ep(proc, res, 1), imag);
 					} else if (is_type_quaternion(t)) {
 					} else if (is_type_quaternion(t)) {
-						res = ir_add_local_generated(proc, tv->type);
+						res = ir_add_local_generated(proc, tv.type);
 						irValue *real = ir_emit_struct_ev(proc, val, 0);
 						irValue *real = ir_emit_struct_ev(proc, val, 0);
 						irValue *imag = ir_emit_struct_ev(proc, val, 1);
 						irValue *imag = ir_emit_struct_ev(proc, val, 1);
 						irValue *jmag = ir_emit_struct_ev(proc, val, 2);
 						irValue *jmag = ir_emit_struct_ev(proc, val, 2);
@@ -4526,9 +4526,9 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 					irValue *s = ir_build_expr(proc, ce->args.e[0]);
 					irValue *s = ir_build_expr(proc, ce->args.e[0]);
 					Type *t = base_type(ir_type(s));
 					Type *t = base_type(ir_type(s));
 					if (is_type_u8_slice(t)) {
 					if (is_type_u8_slice(t)) {
-						return ir_emit_conv(proc, s, tv->type);
+						return ir_emit_conv(proc, s, tv.type);
 					}
 					}
-					irValue *slice = ir_add_local_generated(proc, tv->type);
+					irValue *slice = ir_add_local_generated(proc, tv.type);
 					i64 elem_size = type_size_of(proc->module->allocator, t->Slice.elem);
 					i64 elem_size = type_size_of(proc->module->allocator, t->Slice.elem);
 
 
 					irValue *ptr   = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr);
 					irValue *ptr   = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr);
@@ -4733,9 +4733,9 @@ bool ir_is_elem_const(irModule *m, AstNode *elem, Type *elem_type) {
 	if (elem->kind == AstNode_FieldValue) {
 	if (elem->kind == AstNode_FieldValue) {
 		elem = elem->FieldValue.value;
 		elem = elem->FieldValue.value;
 	}
 	}
-	TypeAndValue *tav = type_and_value_of_expression(m->info, elem);
-	GB_ASSERT(tav != NULL);
-	return tav->value.kind != ExactValue_Invalid;
+	TypeAndValue tav = type_and_value_of_expr(m->info, elem);
+	GB_ASSERT(tav.mode != Addressing_Invalid);
+	return tav.value.kind != ExactValue_Invalid;
 }
 }
 
 
 irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) {
 irAddr ir_build_addr_from_entity(irProcedure *proc, Entity *e, AstNode *expr) {
@@ -4790,9 +4790,9 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 		AstNode *sel = unparen_expr(se->selector);
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
 		if (sel->kind == AstNode_Ident) {
 			String selector = sel->Ident.string;
 			String selector = sel->Ident.string;
-			TypeAndValue *tav = type_and_value_of_expression(proc->module->info, se->expr);
+			TypeAndValue tav = type_and_value_of_expr(proc->module->info, se->expr);
 
 
-			if (tav == NULL) {
+			if (tav.mode == Addressing_Invalid) {
 				// NOTE(bill): Imports
 				// NOTE(bill): Imports
 				Entity *imp = entity_of_ident(proc->module->info, se->expr);
 				Entity *imp = entity_of_ident(proc->module->info, se->expr);
 				if (imp != NULL) {
 				if (imp != NULL) {
@@ -4802,8 +4802,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			}
 			}
 
 
 
 
-			Type *type = base_type(tav->type);
-			if (tav->mode == Addressing_Type) { // Addressing_Type
+			Type *type = base_type(tav.type);
+			if (tav.mode == Addressing_Type) { // Addressing_Type
 				Selection sel = lookup_field(proc->module->allocator, type, selector, true);
 				Selection sel = lookup_field(proc->module->allocator, type, selector, true);
 				Entity *e = sel.entity;
 				Entity *e = sel.entity;
 				GB_ASSERT(e->kind == Entity_Variable);
 				GB_ASSERT(e->kind == Entity_Variable);
@@ -4838,7 +4838,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 			Type *type = type_deref(type_of_expr(proc->module->info, se->expr));
 			Type *type = type_deref(type_of_expr(proc->module->info, se->expr));
 			Type *selector_type = base_type(type_of_expr(proc->module->info, se->selector));
 			Type *selector_type = base_type(type_of_expr(proc->module->info, se->selector));
 			GB_ASSERT_MSG(is_type_integer(selector_type), "%s", type_to_string(selector_type));
 			GB_ASSERT_MSG(is_type_integer(selector_type), "%s", type_to_string(selector_type));
-			ExactValue val = type_and_value_of_expression(proc->module->info, sel)->value;
+			ExactValue val = type_and_value_of_expr(proc->module->info, sel).value;
 			i64 index = val.value_integer;
 			i64 index = val.value_integer;
 
 
 			Selection sel = lookup_field_from_index(proc->module->allocator, type, index);
 			Selection sel = lookup_field_from_index(proc->module->allocator, type, index);
@@ -5009,7 +5009,6 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 
 
 
 
 		case Type_Basic: { // Basic_string
 		case Type_Basic: { // Basic_string
-			TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(ie->expr));
 			irValue *str;
 			irValue *str;
 			irValue *elem;
 			irValue *elem;
 			irValue *len;
 			irValue *len;
@@ -5214,7 +5213,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 						index = sel.index.e[0];
 						index = sel.index.e[0];
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
-						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
+						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
 						Selection sel = lookup_field(proc->module->allocator, bt, st->fields_in_src_order[field_index]->token.string, false);
 						index = sel.index.e[0];
 						index = sel.index.e[0];
 					}
 					}
@@ -5370,7 +5369,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 						index = sel.index.e[0];
 						index = sel.index.e[0];
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
-						TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
+						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
 						Selection sel = lookup_field(proc->module->allocator, bt, field_names[field_index], false);
 						Selection sel = lookup_field(proc->module->allocator, bt, field_names[field_index], false);
 						index = sel.index.e[0];
 						index = sel.index.e[0];
 					}
 					}
@@ -6177,14 +6176,14 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
 		irBlock *done = NULL;
 		irBlock *done = NULL;
 		AstNode *expr = unparen_expr(rs->expr);
 		AstNode *expr = unparen_expr(rs->expr);
 
 
-		TypeAndValue *tav = type_and_value_of_expression(proc->module->info, expr);
+		TypeAndValue tav = type_and_value_of_expr(proc->module->info, expr);
 
 
 		if (is_ast_node_a_range(expr)) {
 		if (is_ast_node_a_range(expr)) {
 			ir_build_range_interval(proc, &expr->BinaryExpr, val_type, &val, &index, &loop, &done);
 			ir_build_range_interval(proc, &expr->BinaryExpr, val_type, &val, &index, &loop, &done);
-		} else if (tav->mode == Addressing_Type) {
+		} else if (tav.mode == Addressing_Type) {
 			TokenPos pos = ast_node_token(expr).pos;
 			TokenPos pos = ast_node_token(expr).pos;
 			gbAllocator a = proc->module->allocator;
 			gbAllocator a = proc->module->allocator;
-			Type *t = tav->type;
+			Type *t = tav.type;
 			GB_ASSERT(is_type_enum(t));
 			GB_ASSERT(is_type_enum(t));
 			Type *enum_ptr = make_type_pointer(a, t);
 			Type *enum_ptr = make_type_pointer(a, t);
 			t = base_type(t);
 			t = base_type(t);
@@ -7158,12 +7157,12 @@ void ir_gen_tree(irGen *s) {
 				if (is_type_any(e->type)) {
 				if (is_type_any(e->type)) {
 
 
 				} else {
 				} else {
-					TypeAndValue *tav = map_tav_get(&info->types, hash_pointer(decl->init_expr));
-					if (tav != NULL) {
-						if (tav->value.kind != ExactValue_Invalid) {
-							ExactValue v = tav->value;
+					TypeAndValue tav = type_and_value_of_expr(info, decl->init_expr);
+					if (tav.mode != Addressing_Invalid) {
+						if (tav.value.kind != ExactValue_Invalid) {
+							ExactValue v = tav.value;
 							// if (v.kind != ExactValue_String) {
 							// if (v.kind != ExactValue_String) {
-								g->Global.value = ir_add_module_constant(m, tav->type, v);
+								g->Global.value = ir_add_module_constant(m, tav.type, v);
 							// }
 							// }
 						}
 						}
 					}
 					}

+ 15 - 15
src/ir_print.c

@@ -490,9 +490,9 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 				if (i > 0) {
 				if (i > 0) {
 					ir_fprintf(f, ", ");
 					ir_fprintf(f, ", ");
 				}
 				}
-				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
-				GB_ASSERT(tav != NULL);
-				ir_print_compound_element(f, m, tav->value, elem_type);
+				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
+				GB_ASSERT(tav.mode != Addressing_Invalid);
+				ir_print_compound_element(f, m, tav.value, elem_type);
 			}
 			}
 			for (isize i = elem_count; i < type->Array.count; i++) {
 			for (isize i = elem_count; i < type->Array.count; i++) {
 				if (i >= elem_count) {
 				if (i >= elem_count) {
@@ -520,23 +520,23 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ir_fprintf(f, "][");
 			ir_fprintf(f, "][");
 
 
 			if (elem_count == 1 && type->Vector.count > 1) {
 			if (elem_count == 1 && type->Vector.count > 1) {
-				TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[0]);
-				GB_ASSERT(tav != NULL);
+				TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[0]);
+				GB_ASSERT(tav.mode != Addressing_Invalid);
 
 
 				for (isize i = 0; i < type->Vector.count; i++) {
 				for (isize i = 0; i < type->Vector.count; i++) {
 					if (i > 0) {
 					if (i > 0) {
 						ir_fprintf(f, ", ");
 						ir_fprintf(f, ", ");
 					}
 					}
-					ir_print_compound_element(f, m, tav->value, elem_type);
+					ir_print_compound_element(f, m, tav.value, elem_type);
 				}
 				}
 			} else {
 			} else {
 				for (isize i = 0; i < elem_count; i++) {
 				for (isize i = 0; i < elem_count; i++) {
 					if (i > 0) {
 					if (i > 0) {
 						ir_fprintf(f, ", ");
 						ir_fprintf(f, ", ");
 					}
 					}
-					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
-					GB_ASSERT(tav != NULL);
-					ir_print_compound_element(f, m, tav->value, elem_type);
+					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
+					GB_ASSERT(tav.mode != Addressing_Invalid);
+					ir_print_compound_element(f, m, tav.value, elem_type);
 				}
 				}
 			}
 			}
 
 
@@ -562,21 +562,21 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 					ast_node(fv, FieldValue, cl->elems.e[i]);
 					ast_node(fv, FieldValue, cl->elems.e[i]);
 					String name = fv->field->Ident.string;
 					String name = fv->field->Ident.string;
 
 
-					TypeAndValue *tav = type_and_value_of_expression(m->info, fv->value);
-					GB_ASSERT(tav != NULL);
+					TypeAndValue tav = type_and_value_of_expr(m->info, fv->value);
+					GB_ASSERT(tav.mode != Addressing_Invalid);
 
 
 					Selection sel = lookup_field(m->allocator, type, name, false);
 					Selection sel = lookup_field(m->allocator, type, name, false);
 					Entity *f = type->Record.fields[sel.index.e[0]];
 					Entity *f = type->Record.fields[sel.index.e[0]];
 
 
-					values[f->Variable.field_index] = tav->value;
+					values[f->Variable.field_index] = tav.value;
 				}
 				}
 			} else {
 			} else {
 				for (isize i = 0; i < value_count; i++) {
 				for (isize i = 0; i < value_count; i++) {
 					Entity *f = type->Record.fields_in_src_order[i];
 					Entity *f = type->Record.fields_in_src_order[i];
-					TypeAndValue *tav = type_and_value_of_expression(m->info, cl->elems.e[i]);
+					TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
 					ExactValue val = {0};
 					ExactValue val = {0};
-					if (tav != NULL) {
-						val = tav->value;
+					if (tav.mode != Addressing_Invalid) {
+						val = tav.value;
 					}
 					}
 					values[f->Variable.field_index] = val;
 					values[f->Variable.field_index] = val;
 				}
 				}

+ 0 - 1305
src/old_vm.c

@@ -1,1305 +0,0 @@
-// TODO(bill): COMPLETELY REWORK THIS ENTIRE INTERPRETER
-#include "dyncall/include/dyncall.h"
-
-struct VirtualMachine;
-
-struct vmValueProc {
-	ssaProcedure *proc; // If `NULL`, use `ptr` instead and call external procedure
-	void *        ptr;
-};
-
-
-struct vmValue {
-	// NOTE(bill): Shouldn't need to store type here as the type checking
-	// has already been handled in the SSA
-	union {
-		f32            val_f32;
-		f64            val_f64;
-		void *         val_ptr;
-		i64            val_int;
-		vmValueProc    val_proc;
-	};
-	Array<vmValue> val_comp; // NOTE(bill): Will be freed through "stack"
-	Type *type;
-};
-
-vmValue vm_make_value_ptr(Type *type, void *ptr) {
-	GB_ASSERT(is_type_pointer(type));
-	vmValue v = {0};
-	v.type = default_type(type);
-	v.val_ptr = ptr;
-	return v;
-}
-vmValue vm_make_value_int(Type *type, i64 i) {
-	GB_ASSERT(is_type_integer(type) ||
-	          is_type_boolean(type) ||
-	          is_type_enum(type));
-	vmValue v = {0};
-	v.type = default_type(type);
-	v.val_int = i;
-	return v;
-}
-vmValue vm_make_value_f32(Type *type, f32 f) {
-	GB_ASSERT(is_type_f32(type));
-	vmValue v = {0};
-	v.type = default_type(type);
-	v.val_f32 = f;
-	return v;
-}
-vmValue vm_make_value_f64(Type *type, f64 f) {
-	GB_ASSERT(is_type_f64(type));
-	vmValue v = {0};
-	v.type = default_type(type);
-	v.val_f64 = f;
-	return v;
-}
-vmValue vm_make_value_comp(Type *type, gbAllocator allocator, isize count) {
-	GB_ASSERT(is_type_string(type)    ||
-	          is_type_any   (type)    ||
-	          is_type_array (type)    ||
-	          is_type_vector(type)    ||
-	          is_type_slice (type)    ||
-	          is_type_maybe (type)    ||
-	          is_type_struct(type)    ||
-	          is_type_union(type)     ||
-	          is_type_raw_union(type) ||
-	          is_type_tuple (type)    ||
-	          is_type_proc  (type));
-	vmValue v = {0};
-	v.type = default_type(type);
-	array_init_count(&v.val_comp, allocator, count);
-	return v;
-}
-
-
-
-
-
-
-struct vmFrame {
-	VirtualMachine *  vm;
-	vmFrame *         caller;
-	ssaProcedure *    curr_proc;
-	ssaBlock *        prev_block;
-	ssaBlock *        curr_block;
-	i32               instr_index; // For the current block
-
-	Map<vmValue>      values; // Key: ssaValue *
-	gbTempArenaMemory temp_arena_memory;
-	gbAllocator       stack_allocator;
-	Array<void *>     locals; // Memory to locals
-	vmValue           result;
-};
-
-struct VirtualMachine {
-	ssaModule *         module;
-	gbArena             stack_arena;
-	gbAllocator         stack_allocator;
-	gbAllocator         heap_allocator;
-	Array<vmFrame>      frame_stack;
-	Map<vmValue>        globals;             // Key: ssaValue *
-	Map<vmValue>        const_compound_lits; // Key: ssaValue *
-	vmValue             exit_value;
-};
-
-void    vm_exec_instr   (VirtualMachine *vm, ssaValue *value);
-vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value);
-void    vm_store        (VirtualMachine *vm, void *dst, vmValue val, Type *type);
-vmValue vm_load         (VirtualMachine *vm, void *ptr, Type *type);
-void    vm_print_value  (vmValue value, Type *type);
-
-void vm_jump_block(vmFrame *f, ssaBlock *target) {
-	f->prev_block = f->curr_block;
-	f->curr_block = target;
-	f->instr_index = 0;
-}
-
-
-vmFrame *vm_back_frame(VirtualMachine *vm) {
-	if (vm->frame_stack.count > 0) {
-		return &vm->frame_stack[vm->frame_stack.count-1];
-	}
-	return NULL;
-}
-
-i64 vm_type_size_of(VirtualMachine *vm, Type *type) {
-	return type_size_of(vm->module->sizes, vm->heap_allocator, type);
-}
-i64 vm_type_align_of(VirtualMachine *vm, Type *type) {
-	return type_align_of(vm->module->sizes, vm->heap_allocator, type);
-}
-i64 vm_type_offset_of(VirtualMachine *vm, Type *type, i64 index) {
-	return type_offset_of(vm->module->sizes, vm->heap_allocator, type, index);
-}
-
-
-void vm_init(VirtualMachine *vm, ssaModule *module) {
-	gb_arena_init_from_allocator(&vm->stack_arena, heap_allocator(), gb_megabytes(64));
-
-	vm->module = module;
-	vm->stack_allocator = gb_arena_allocator(&vm->stack_arena);
-	vm->heap_allocator = heap_allocator();
-	array_init(&vm->frame_stack, vm->heap_allocator);
-	map_init(&vm->globals, vm->heap_allocator);
-	map_init(&vm->const_compound_lits, vm->heap_allocator);
-
-	for_array(i, vm->module->values.entries) {
-		ssaValue *v = vm->module->values.entries[i].value;
-		switch (v->kind) {
-		case ssaValue_Global: {
-			Type *t = ssa_type(v);
-			GB_ASSERT(is_type_pointer(t));
-			i64 size  = vm_type_size_of(vm, t);
-			i64 align = vm_type_align_of(vm, t);
-			void *mem = gb_alloc_align(vm->heap_allocator, size, align);
-			if (v->Global.value != NULL && v->Global.value->kind == ssaValue_Constant) {
-				vm_store(vm, mem, vm_operand_value(vm, v->Global.value), type_deref(t));
-			}
-			map_set(&vm->globals, hash_pointer(v), vm_make_value_ptr(t, mem));
-		} break;
-		}
-	}
-
-}
-void vm_destroy(VirtualMachine *vm) {
-	array_free(&vm->frame_stack);
-	map_destroy(&vm->globals);
-	map_destroy(&vm->const_compound_lits);
-	gb_arena_free(&vm->stack_arena);
-}
-
-
-
-
-
-
-void vm_set_value(vmFrame *f, ssaValue *v, vmValue val) {
-	if (v != NULL) {
-		GB_ASSERT(ssa_type(v) != NULL);
-		map_set(&f->values, hash_pointer(v), val);
-	}
-}
-
-
-
-vmFrame *vm_push_frame(VirtualMachine *vm, ssaProcedure *proc) {
-	vmFrame frame = {0};
-
-	frame.vm          = vm;
-	frame.curr_proc   = proc;
-	frame.prev_block  = proc->blocks[0];
-	frame.curr_block  = proc->blocks[0];
-	frame.instr_index = 0;
-	frame.caller      = vm_back_frame(vm);
-	frame.stack_allocator   = vm->stack_allocator;
-	frame.temp_arena_memory = gb_temp_arena_memory_begin(&vm->stack_arena);
-
-	map_init(&frame.values, vm->heap_allocator);
-	array_init(&frame.locals, vm->heap_allocator, proc->local_count);
-	array_add(&vm->frame_stack, frame);
-	return vm_back_frame(vm);
-}
-
-void vm_pop_frame(VirtualMachine *vm) {
-	vmFrame *f = vm_back_frame(vm);
-
-	gb_temp_arena_memory_end(f->temp_arena_memory);
-	array_free(&f->locals);
-	map_destroy(&f->values);
-
-	array_pop(&vm->frame_stack);
-}
-
-
-vmValue vm_call_proc(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue> values) {
-	Type *type = base_type(proc->type);
-	GB_ASSERT_MSG(type->Proc.param_count == values.count,
-	              "Incorrect number of arguments passed into procedure call!\n"
-	              "%.*s -> %td vs %td",
-	              LIT(proc->name),
-	              type->Proc.param_count, values.count);
-	Type *result_type = type->Proc.results;
-	if (result_type != NULL &&
-	    result_type->Tuple.variable_count == 1) {
-		result_type = result_type->Tuple.variables[0]->type;
-	}
-
-	if (proc->body == NULL) {
-		// GB_PANIC("TODO(bill): external procedure");
-		gb_printf_err("TODO(bill): external procedure: %.*s\n", LIT(proc->name));
-		vmValue result = {0};
-		result.type = result_type;
-		return result;
-	}
-
-	void *result_mem = NULL;
-	if (result_type != NULL) {
-		result_mem = gb_alloc_align(vm->stack_allocator,
-		                            vm_type_size_of(vm, result_type),
-		                            vm_type_align_of(vm, result_type));
-	}
-
-	gb_printf("call: %.*s\n", LIT(proc->name));
-
-	vmFrame *f = vm_push_frame(vm, proc);
-	for_array(i, proc->params) {
-		vm_set_value(f, proc->params[i], values[i]);
-	}
-
-	while (f->curr_block != NULL) {
-		ssaValue *curr_instr = f->curr_block->instrs[f->instr_index++];
-		vm_exec_instr(vm, curr_instr);
-	}
-
-
-
-
-	if (type->Proc.result_count > 0) {
-		vmValue r = f->result;
-
-		gb_printf("%.*s -> ", LIT(proc->name));
-		vm_print_value(r, result_type);
-		gb_printf("\n");
-
-		vm_store(vm, result_mem, r, result_type);
-	}
-
-	vm_pop_frame(vm);
-	if (result_mem != NULL) {
-		return vm_load(vm, result_mem, result_type);
-	}
-
-	vmValue void_result = {0};
-	return void_result;
-}
-
-
-ssaProcedure *vm_lookup_procedure(VirtualMachine *vm, String name) {
-	ssaValue *v = ssa_lookup_member(vm->module, name);
-	GB_ASSERT(v->kind == ssaValue_Proc);
-	return &v->Proc;
-}
-
-vmValue vm_call_proc_by_name(VirtualMachine *vm, String name, Array<vmValue> args) {
-	return vm_call_proc(vm, vm_lookup_procedure(vm, name), args);
-}
-
-vmValue vm_exact_value(VirtualMachine *vm, ssaValue *ptr, ExactValue value, Type *t) {
-	Type *original_type = t;
-	t = base_type(get_enum_base_type(t));
-	// i64 size = vm_type_size_of(vm, t);
-	if (is_type_boolean(t)) {
-		return vm_make_value_int(original_type, value.value_bool);
-	} else if (is_type_integer(t)) {
-		return vm_make_value_int(original_type, value.value_integer);
-	} else if (is_type_float(t)) {
-		if (t->Basic.kind == Basic_f32) {
-			return vm_make_value_f32(original_type, cast(f32)value.value_float);
-		} else if (t->Basic.kind == Basic_f64) {
-			return vm_make_value_f64(original_type, cast(f64)value.value_float);
-		}
-	} else if (is_type_pointer(t)) {
-		return vm_make_value_ptr(original_type, cast(void *)cast(intptr)value.value_pointer);
-	} else if (is_type_string(t)) {
-		vmValue result = vm_make_value_comp(original_type, vm->stack_allocator, 2);
-
-		String str = value.value_string;
-		i64 len = str.len;
-		u8 *text = gb_alloc_array(vm->heap_allocator, u8, len);
-		gb_memcopy(text, str.text, len);
-
-		result.val_comp[0] = vm_make_value_ptr(t_u8_ptr, text);
-		result.val_comp[1] = vm_make_value_int(t_int, len);
-
-		return result;
-	} else if (value.kind == ExactValue_Compound) {
-		if (ptr != NULL) {
-			vmValue *found = map_get(&vm->const_compound_lits, hash_pointer(ptr));
-			if (found != NULL)  {
-				return *found;
-			}
-		}
-
-		ast_node(cl, CompoundLit, value.value_compound);
-
-		if (is_type_array(t)) {
-			vmValue result = {0};
-
-			isize elem_count = cl->elems.count;
-			if (elem_count == 0) {
-				if (ptr != NULL) {
-					map_set(&vm->const_compound_lits, hash_pointer(ptr), result);
-				}
-				return result;
-			}
-
-			Type *type = base_type(t);
-			result = vm_make_value_comp(t, vm->heap_allocator, type->Array.count);
-			for (isize i = 0; i < elem_count; i++) {
-				TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]);
-				vmValue elem = vm_exact_value(vm, NULL, tav->value, tav->type);
-				result.val_comp[i] = elem;
-			}
-
-			if (ptr != NULL) {
-				map_set(&vm->const_compound_lits, hash_pointer(ptr), result);
-			}
-
-			return result;
-		} else if (is_type_vector(t)) {
-			vmValue result = {0};
-
-			isize elem_count = cl->elems.count;
-			if (elem_count == 0) {
-				if (ptr != NULL) {
-					map_set(&vm->const_compound_lits, hash_pointer(ptr), result);
-				}
-				return result;
-			}
-
-			Type *type = base_type(t);
-			result = vm_make_value_comp(t, vm->heap_allocator, type->Array.count);
-			for (isize i = 0; i < elem_count; i++) {
-				TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]);
-				vmValue elem = vm_exact_value(vm, NULL, tav->value, tav->type);
-				result.val_comp[i] = elem;
-			}
-
-			if (ptr != NULL) {
-				map_set(&vm->const_compound_lits, hash_pointer(ptr), result);
-			}
-
-			return result;
-		} else if (is_type_struct(t)) {
-			ast_node(cl, CompoundLit, value.value_compound);
-
-			isize value_count = t->Record.field_count;
-			vmValue result = vm_make_value_comp(t, vm->heap_allocator, value_count);
-
-			if (cl->elems.count == 0) {
-				return result;
-			}
-
-			if (cl->elems[0]->kind == AstNode_FieldValue) {
-				isize elem_count = cl->elems.count;
-				for (isize i = 0; i < elem_count; i++) {
-					ast_node(fv, FieldValue, cl->elems[i]);
-					String name = fv->field->Ident.string;
-
-					TypeAndValue *tav = type_and_value_of_expression(vm->module->info, fv->value);
-					GB_ASSERT(tav != NULL);
-
-					Selection sel = lookup_field(vm->heap_allocator, t, name, false);
-					Entity *f = t->Record.fields[sel.index[0]];
-
-					result.val_comp[f->Variable.field_index] = vm_exact_value(vm, NULL, tav->value, f->type);
-				}
-			} else {
-				for (isize i = 0; i < value_count; i++) {
-					TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]);
-					GB_ASSERT(tav != NULL);
-					Entity *f = t->Record.fields_in_src_order[i];
-					result.val_comp[f->Variable.field_index] = vm_exact_value(vm, NULL, tav->value, f->type);
-				}
-			}
-
-			return result;
-		} else {
-			GB_PANIC("TODO(bill): Other compound types\n");
-		}
-
-	} else if (value.kind == ExactValue_Invalid) {
-		vmValue zero_result = {0};
-		zero_result.type = t;
-		return zero_result;
-	} else {
-		gb_printf_err("TODO(bill): Other constant types: %s\n", type_to_string(original_type));
-	}
-
-	GB_ASSERT_MSG(t == NULL, "%s - %d", type_to_string(t), value.kind);
-	vmValue void_result = {0};
-	return void_result;
-}
-
-
-vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value) {
-	vmFrame *f = vm_back_frame(vm);
-	vmValue v = {0};
-	switch (value->kind) {
-	case ssaValue_Constant: {
-		v = vm_exact_value(vm, value, value->Constant.value, value->Constant.type);
-	} break;
-	case ssaValue_ConstantSlice: {
-		ssaValueConstant *cs = &value->ConstantSlice;
-		v = vm_make_value_comp(ssa_type(value), vm->stack_allocator, 3);
-		v.val_comp[0] = vm_operand_value(vm, cs->backing_array);
-		v.val_comp[1] = vm_make_value_int(t_int, cs->count);
-		v.val_comp[2] = vm_make_value_int(t_int, cs->count);
-	} break;
-	case ssaValue_Nil:
-		GB_PANIC("TODO(bill): ssaValue_Nil");
-		break;
-	case ssaValue_TypeName:
-		GB_PANIC("ssaValue_TypeName has no operand value");
-		break;
-	case ssaValue_Global:
-		v = *map_get(&vm->globals, hash_pointer(value));
-		break;
-	case ssaValue_Param:
-		v = *map_get(&f->values, hash_pointer(value));
-		break;
-	case ssaValue_Proc: {
-		v.type = ssa_type(value);
-		v.val_proc.proc = &value->Proc;
-		// GB_PANIC("TODO(bill): ssaValue_Proc");
-	} break;
-	case ssaValue_Block:
-		GB_PANIC("ssaValue_Block has no operand value");
-		break;
-	case ssaValue_Instr: {
-		vmValue *found = map_get(&f->values, hash_pointer(value));
-		if (found) {
-			v = *found;
-		} else {
-			GB_PANIC("Invalid instruction");
-		}
-	} break;
-	}
-
-	return v;
-}
-
-void vm_store_integer(VirtualMachine *vm, void *dst, vmValue val) {
-	// TODO(bill): I assume little endian here
-	GB_ASSERT(dst != NULL);
-	Type *type = val.type;
-	GB_ASSERT_MSG(is_type_integer(type) || is_type_boolean(type),
-	              "\nExpected integer/boolean, got %s (%s)",
-	              type_to_string(type),
-	              type_to_string(base_type(type)));
-	i64 size = vm_type_size_of(vm, type);
-	gb_memcopy(dst, &val.val_int, size);
-}
-
-void vm_store_pointer(VirtualMachine *vm, void *dst, vmValue val) {
-	// TODO(bill): I assume little endian here
-	GB_ASSERT(dst != NULL);
-	GB_ASSERT(is_type_pointer(val.type));
-	gb_memcopy(dst, &val.val_ptr, vm_type_size_of(vm, t_rawptr));
-}
-
-
-void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) {
-	i64 size = vm_type_size_of(vm, type);
-	Type *original_type = type;
-	// NOTE(bill): enums are pretty much integers
-	type = base_type(get_enum_base_type(type));
-
-	switch (type->kind) {
-	case Type_Basic:
-		switch (type->Basic.kind) {
-		case Basic_bool:
-		case Basic_i8:
-		case Basic_u8:
-		case Basic_i16:
-		case Basic_u16:
-		case Basic_i32:
-		case Basic_u32:
-		case Basic_i64:
-		case Basic_u64:
-		case Basic_int:
-		case Basic_uint:
-			vm_store_integer(vm, dst, val);
-			break;
-		case Basic_f32:
-			*cast(f32 *)dst = val.val_f32;
-			break;
-		case Basic_f64:
-			*cast(f64 *)dst = val.val_f64;
-			break;
-		case Basic_rawptr:
-			vm_store_pointer(vm, dst, val); // NOTE(bill): A pointer can be treated as an integer
-			break;
-		case Basic_string: {
-			i64 word_size = vm_type_size_of(vm, t_int);
-
-			u8 *mem = cast(u8 *)dst;
-			vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]);
-			vm_store_integer(vm, mem+1*word_size, val.val_comp[1]);
-		} break;
-		case Basic_any: {
-			i64 word_size = vm_type_size_of(vm, t_int);
-
-			u8 *mem = cast(u8 *)dst;
-			vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]);
-			vm_store_pointer(vm, mem+1*word_size, val.val_comp[1]);
-		} break;
-		default:
-			gb_printf_err("TODO(bill): other basic types for `vm_store` %s\n", type_to_string(type));
-			break;
-		}
-		break;
-
-	case Type_Pointer:
-		vm_store_pointer(vm, dst, val);
-		break;
-
-	case Type_Record: {
-		u8 *mem = cast(u8 *)dst;
-		gb_zero_size(mem, size);
-
-		if (is_type_struct(type)) {
-			GB_ASSERT_MSG(type->Record.field_count >= val.val_comp.count,
-			              "%td vs %td",
-			              type->Record.field_count, val.val_comp.count);
-
-			isize field_count = gb_min(val.val_comp.count, type->Record.field_count);
-
-			for (isize i = 0; i < field_count; i++) {
-				Entity *f = type->Record.fields[i];
-				i64 offset = vm_type_offset_of(vm, type, i);
-				vm_store(vm, mem+offset, val.val_comp[i], f->type);
-			}
-		} else if (is_type_union(type)) {
-			GB_ASSERT(val.val_comp.count == 2);
-			i64 word_size = vm_type_size_of(vm, t_int);
-			i64 size_of_union = vm_type_size_of(vm, type) - word_size;
-			for (isize i = 0; i < size_of_union; i++) {
-				mem[i] = cast(u8)val.val_comp[0].val_comp[i].val_int;
-			}
-			vm_store_integer(vm, mem + size_of_union, val.val_comp[1]);
-
-		} else if (is_type_raw_union(type)) {
-			GB_ASSERT(val.val_comp.count == 1);
-			i64 word_size = vm_type_size_of(vm, t_int);
-			i64 size_of_union = vm_type_size_of(vm, type) - word_size;
-			for (isize i = 0; i < size_of_union; i++) {
-				mem[i] = cast(u8)val.val_comp[0].val_comp[i].val_int;
-			}
-		} else {
-			GB_PANIC("Unknown record type: %s", type_to_string(type));
-		}
-	} break;
-
-	case Type_Tuple: {
-		u8 *mem = cast(u8 *)dst;
-
-		GB_ASSERT_MSG(type->Tuple.variable_count >= val.val_comp.count,
-		              "%td vs %td",
-		              type->Tuple.variable_count, val.val_comp.count);
-
-		isize variable_count = gb_min(val.val_comp.count, type->Tuple.variable_count);
-
-		for (isize i = 0; i < variable_count; i++) {
-			Entity *f = type->Tuple.variables[i];
-			void *ptr = mem + vm_type_offset_of(vm, type, i);
-			vm_store(vm, ptr, val.val_comp[i], f->type);
-		}
-	} break;
-
-	case Type_Array: {
-		Type *elem_type = type->Array.elem;
-		u8 *mem = cast(u8 *)dst;
-		i64 elem_size = vm_type_size_of(vm, elem_type);
-		i64 elem_count = gb_min(val.val_comp.count, type->Array.count);
-
-		for (i64 i = 0; i < elem_count; i++) {
-			vm_store(vm, mem + i*elem_size, val.val_comp[i], elem_type);
-		}
-	} break;
-
-	case Type_Vector: {
-		Type *elem_type = type->Array.elem;
-		GB_ASSERT_MSG(!is_type_boolean(elem_type), "TODO(bill): Booleans of vectors");
-		u8 *mem = cast(u8 *)dst;
-		i64 elem_size = vm_type_size_of(vm, elem_type);
-		i64 elem_count = gb_min(val.val_comp.count, type->Array.count);
-
-		for (i64 i = 0; i < elem_count; i++) {
-			vm_store(vm, mem + i*elem_size, val.val_comp[i], elem_type);
-		}
-	} break;
-
-	case Type_Slice: {
-		i64 word_size = vm_type_size_of(vm, t_int);
-
-		u8 *mem = cast(u8 *)dst;
-		vm_store_pointer(vm, mem+0*word_size, val.val_comp[0]);
-		vm_store_integer(vm, mem+1*word_size, val.val_comp[1]);
-		vm_store_integer(vm, mem+2*word_size, val.val_comp[2]);
-	} break;
-
-	default:
-		gb_printf_err("TODO(bill): other types for `vm_store` %s\n", type_to_string(type));
-		break;
-	}
-}
-
-vmValue vm_load_integer(VirtualMachine *vm, void *ptr, Type *type) {
-	// TODO(bill): I assume little endian here
-	vmValue v = {0};
-	v.type = type;
-	GB_ASSERT(is_type_integer(type) || is_type_boolean(type));
-	// NOTE(bill): Only load the needed amount
-	gb_memcopy(&v.val_int, ptr, vm_type_size_of(vm, type));
-	return v;
-}
-
-vmValue vm_load_pointer(VirtualMachine *vm, void *ptr, Type *type) {
-	// TODO(bill): I assume little endian here
-	vmValue v = {0};
-	v.type = type;
-	GB_ASSERT(is_type_pointer(type));
-	// NOTE(bill): Only load the needed amount
-	gb_memcopy(&v.val_int, ptr, vm_type_size_of(vm, type));
-	return v;
-}
-
-
-vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
-	i64 size = vm_type_size_of(vm, type);
-	Type *original_type = type;
-	type = base_type(get_enum_base_type(type));
-
-	switch (type->kind) {
-	case Type_Basic:
-		switch (type->Basic.kind) {
-		case Basic_bool:
-		case Basic_i8:
-		case Basic_u8:
-		case Basic_i16:
-		case Basic_u16:
-		case Basic_i32:
-		case Basic_u32:
-		case Basic_i64:
-		case Basic_u64:
-		case Basic_int:
-		case Basic_uint:
-			return vm_load_integer(vm, ptr, original_type);
-		case Basic_f32:
-			return vm_make_value_f32(original_type, *cast(f32 *)ptr);
-		case Basic_f64:
-			return vm_make_value_f64(original_type, *cast(f64 *)ptr);
-		case Basic_rawptr:
-			return vm_load_pointer(vm, ptr, original_type);
-
-
-		case Basic_string: {
-			u8 *mem = cast(u8 *)ptr;
-			i64 word_size = vm_type_size_of(vm, t_int);
-			vmValue result = vm_make_value_comp(type, vm->stack_allocator, 2);
-			result.val_comp[0] = vm_load_pointer(vm, mem+0*word_size, t_u8_ptr);
-			result.val_comp[1] = vm_load_integer(vm, mem+1*word_size, t_int);
-			return result;
-		} break;
-
-		default:
-			GB_PANIC("TODO(bill): other basic types for `vm_load` %s", type_to_string(type));
-			break;
-		}
-		break;
-
-	case Type_Pointer:
-		return vm_load_pointer(vm, ptr, original_type);
-
-	case Type_Array: {
-		i64 count = type->Array.count;
-		Type *elem_type = type->Array.elem;
-		i64 elem_size = vm_type_size_of(vm, elem_type);
-
-		vmValue result = vm_make_value_comp(type, vm->stack_allocator, count);
-
-		u8 *mem = cast(u8 *)ptr;
-		for (isize i = 0; i < count; i++) {
-			i64 offset = elem_size*i;
-			vmValue val = vm_load(vm, mem+offset, elem_type);
-			result.val_comp[i] = val;
-		}
-
-		return result;
-	} break;
-
-	case Type_Slice: {
-		Type *elem_type = type->Slice.elem;
-		i64 elem_size = vm_type_size_of(vm, elem_type);
-		i64 word_size = vm_type_size_of(vm, t_int);
-
-		vmValue result = vm_make_value_comp(type, vm->stack_allocator, 3);
-
-		u8 *mem = cast(u8 *)ptr;
-		result.val_comp[0] = vm_load(vm, mem+0*word_size, t_rawptr); // data
-		result.val_comp[1] = vm_load(vm, mem+1*word_size, t_int);    // count
-		result.val_comp[2] = vm_load(vm, mem+2*word_size, t_int);    // capacity
-		return result;
-	} break;
-
-	case Type_Record: {
-		if (is_type_struct(type)) {
-			isize field_count = type->Record.field_count;
-
-			vmValue result = vm_make_value_comp(type, vm->stack_allocator, field_count);
-
-			u8 *mem = cast(u8 *)ptr;
-			for (isize i = 0; i < field_count; i++) {
-				Entity *f = type->Record.fields[i];
-				i64 offset = vm_type_offset_of(vm, type, i);
-				result.val_comp[i] = vm_load(vm, mem+offset, f->type);
-			}
-
-			return result;
-		} else if (is_type_union(type)) {
-			i64 word_size = vm_type_size_of(vm, t_int);
-			i64 size_of_union = vm_type_size_of(vm, type) - word_size;
-			u8 *mem = cast(u8 *)ptr;
-
-			vmValue result = vm_make_value_comp(type, vm->stack_allocator, 2);
-			result.val_comp[0] = vm_load(vm, mem, make_type_array(vm->stack_allocator, t_u8, size_of_union));
-			result.val_comp[1] = vm_load(vm, mem+size_of_union, t_int);
-			return result;
-		} else if (is_type_raw_union(type)) {
-			gb_printf_err("TODO(bill): load raw_union\n");
-		} else {
-			gb_printf_err("TODO(bill): load other records\n");
-		}
-	} break;
-
-	case Type_Tuple: {
-		isize count = type->Tuple.variable_count;
-
-		vmValue result = vm_make_value_comp(type, vm->stack_allocator, count);
-
-		u8 *mem = cast(u8 *)ptr;
-		for (isize i = 0; i < count; i++) {
-			Entity *f = type->Tuple.variables[i];
-			i64 offset = vm_type_offset_of(vm, type, i);
-			result.val_comp[i] = vm_load(vm, mem+offset, f->type);
-		}
-		return result;
-	} break;
-
-	default:
-		GB_PANIC("TODO(bill): other types for `vm_load` %s", type_to_string(type));
-		break;
-	}
-
-	GB_ASSERT(type == NULL);
-	vmValue void_result = {0};
-	return void_result;
-}
-
-vmValue vm_exec_binary_op(VirtualMachine *vm, Type *type, vmValue lhs, vmValue rhs, TokenKind op) {
-	vmValue result = {0};
-
-	type = base_type(type);
-	if (is_type_vector(type)) {
-		Type *elem = type->Vector.elem;
-		i64 count = type->Vector.count;
-
-		result = vm_make_value_comp(type, vm->stack_allocator, count);
-
-		for (i64 i = 0; i < count; i++) {
-			result.val_comp[i] = vm_exec_binary_op(vm, elem, lhs.val_comp[i], rhs.val_comp[i], op);
-		}
-
-		return result;
-	}
-
-	if (gb_is_between(op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
-		if (is_type_integer(type) || is_type_boolean(type)) {
-			// TODO(bill): Do I need to take into account the size of the integer?
-			switch (op) {
-			case Token_CmpEq: result.val_int = lhs.val_int == rhs.val_int; break;
-			case Token_NotEq: result.val_int = lhs.val_int != rhs.val_int; break;
-			case Token_Lt:    result.val_int = lhs.val_int <  rhs.val_int; break;
-			case Token_Gt:    result.val_int = lhs.val_int >  rhs.val_int; break;
-			case Token_LtEq:  result.val_int = lhs.val_int <= rhs.val_int; break;
-			case Token_GtEq:  result.val_int = lhs.val_int >= rhs.val_int; break;
-			}
-		} else if (type == t_f32) {
-			switch (op) {
-			case Token_CmpEq: result.val_f32 = lhs.val_f32 == rhs.val_f32; break;
-			case Token_NotEq: result.val_f32 = lhs.val_f32 != rhs.val_f32; break;
-			case Token_Lt:    result.val_f32 = lhs.val_f32 <  rhs.val_f32; break;
-			case Token_Gt:    result.val_f32 = lhs.val_f32 >  rhs.val_f32; break;
-			case Token_LtEq:  result.val_f32 = lhs.val_f32 <= rhs.val_f32; break;
-			case Token_GtEq:  result.val_f32 = lhs.val_f32 >= rhs.val_f32; break;
-			}
-		} else if (type == t_f64) {
-			switch (op) {
-			case Token_CmpEq: result.val_f64 = lhs.val_f64 == rhs.val_f64; break;
-			case Token_NotEq: result.val_f64 = lhs.val_f64 != rhs.val_f64; break;
-			case Token_Lt:    result.val_f64 = lhs.val_f64 <  rhs.val_f64; break;
-			case Token_Gt:    result.val_f64 = lhs.val_f64 >  rhs.val_f64; break;
-			case Token_LtEq:  result.val_f64 = lhs.val_f64 <= rhs.val_f64; break;
-			case Token_GtEq:  result.val_f64 = lhs.val_f64 >= rhs.val_f64; break;
-			}
-		} else if (is_type_string(type)) {
-			Array<vmValue> args = {0};
-			array_init_count(&args, vm->stack_allocator, 2);
-			args[0] = lhs;
-			args[1] = rhs;
-			switch (op) {
-			case Token_CmpEq: result = vm_call_proc_by_name(vm, make_string("__string_eq"), args); break;
-			case Token_NotEq: result = vm_call_proc_by_name(vm, make_string("__string_ne"), args); break;
-			case Token_Lt:    result = vm_call_proc_by_name(vm, make_string("__string_lt"), args); break;
-			case Token_Gt:    result = vm_call_proc_by_name(vm, make_string("__string_gt"), args); break;
-			case Token_LtEq:  result = vm_call_proc_by_name(vm, make_string("__string_le"), args); break;
-			case Token_GtEq:  result = vm_call_proc_by_name(vm, make_string("__string_ge"), args); break;
-			}
-		} else {
-			GB_PANIC("TODO(bill): Vector BinaryOp");
-		}
-	} else {
-		if (is_type_integer(type) || is_type_boolean(type)) {
-			switch (op) {
-			case Token_Add: result.val_int = lhs.val_int + rhs.val_int;  break;
-			case Token_Sub: result.val_int = lhs.val_int - rhs.val_int;  break;
-			case Token_And: result.val_int = lhs.val_int & rhs.val_int;  break;
-			case Token_Or:  result.val_int = lhs.val_int | rhs.val_int;  break;
-			case Token_Xor: result.val_int = lhs.val_int ^ rhs.val_int;  break;
-			case Token_Shl: result.val_int = lhs.val_int << rhs.val_int; break;
-			case Token_Shr: result.val_int = lhs.val_int >> rhs.val_int; break;
-			case Token_Mul: result.val_int = lhs.val_int * rhs.val_int;  break;
-			case Token_Not: result.val_int = lhs.val_int ^ rhs.val_int;  break;
-
-			case Token_AndNot: result.val_int = lhs.val_int & (~rhs.val_int); break;
-
-			// TODO(bill): Take into account size of integer and signedness
-			case Token_Quo: GB_PANIC("TODO(bill): BinaryOp Integer Token_Quo"); break;
-			case Token_Mod: GB_PANIC("TODO(bill): BinaryOp Integer Token_Mod"); break;
-
-			}
-		} else if (is_type_float(type)) {
-			if (type == t_f32) {
-				switch (op) {
-				case Token_Add: result.val_f32 = lhs.val_f32 + rhs.val_f32;  break;
-				case Token_Sub: result.val_f32 = lhs.val_f32 - rhs.val_f32;  break;
-				case Token_Mul: result.val_f32 = lhs.val_f32 * rhs.val_f32;  break;
-				case Token_Quo: result.val_f32 = lhs.val_f32 / rhs.val_f32;  break;
-
-				case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f32 Token_Mod"); break;
-				}
-			} else if (type == t_f64) {
-				switch (op) {
-				case Token_Add: result.val_f64 = lhs.val_f64 + rhs.val_f64;  break;
-				case Token_Sub: result.val_f64 = lhs.val_f64 - rhs.val_f64;  break;
-				case Token_Mul: result.val_f64 = lhs.val_f64 * rhs.val_f64;  break;
-				case Token_Quo: result.val_f64 = lhs.val_f64 / rhs.val_f64;  break;
-
-				case Token_Mod: GB_PANIC("TODO(bill): BinaryOp f64 Token_Mod"); break;
-				}
-			}
-		} else {
-			GB_PANIC("Invalid binary op type");
-		}
-	}
-
-	return result;
-}
-
-void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
-	GB_ASSERT(value != NULL);
-	GB_ASSERT(value->kind == ssaValue_Instr);
-	ssaInstr *instr = &value->Instr;
-	vmFrame *f = vm_back_frame(vm);
-
-#if 0
-	if (instr->kind != ssaInstr_Comment) {
-		gb_printf("exec_instr: %.*s\n", LIT(ssa_instr_strings[instr->kind]));
-	}
-#endif
-
-	switch (instr->kind) {
-	case ssaInstr_StartupRuntime: {
-#if 1
-		Array<vmValue> args = {0}; // Empty
-		vm_call_proc_by_name(vm, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), args); // NOTE(bill): No return value
-#endif
-	} break;
-
-	case ssaInstr_Comment:
-		break;
-
-	case ssaInstr_Local: {
-		Type *type = ssa_type(value);
-		GB_ASSERT(is_type_pointer(type));
-		isize size  = gb_max(1, vm_type_size_of(vm, type));
-		isize align = gb_max(1, vm_type_align_of(vm, type));
-		void *memory = gb_alloc_align(vm->stack_allocator, size, align);
-		GB_ASSERT(memory != NULL);
-		vm_set_value(f, value, vm_make_value_ptr(type, memory));
-		array_add(&f->locals, memory);
-	} break;
-
-	case ssaInstr_ZeroInit: {
-		Type *t = type_deref(ssa_type(instr->ZeroInit.address));
-		vmValue addr = vm_operand_value(vm, instr->ZeroInit.address);
-		void *data = addr.val_ptr;
-		i64 size = vm_type_size_of(vm, t);
-		gb_zero_size(data, size);
-	} break;
-
-	case ssaInstr_Store: {
-		vmValue addr = vm_operand_value(vm, instr->Store.address);
-		vmValue val = vm_operand_value(vm, instr->Store.value);
-		GB_ASSERT(val.type != NULL);
-		Type *t = type_deref(ssa_type(instr->Store.address));
-		vm_store(vm, addr.val_ptr, val, t);
-	} break;
-
-	case ssaInstr_Load: {
-		vmValue addr = vm_operand_value(vm, instr->Load.address);
-		Type *t = ssa_type(value);
-		vmValue v = vm_load(vm, addr.val_ptr, t);
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_ArrayElementPtr: {
-		vmValue address    = vm_operand_value(vm, instr->ArrayElementPtr.address);
-		vmValue elem_index = vm_operand_value(vm, instr->ArrayElementPtr.elem_index);
-
-		Type *t = ssa_type(instr->ArrayElementPtr.address);
-		GB_ASSERT(is_type_pointer(t));
-		i64 elem_size = vm_type_size_of(vm, type_deref(t));
-		void *ptr = cast(u8 *)address.val_ptr + elem_index.val_int*elem_size;
-		vm_set_value(f, value, vm_make_value_ptr(t, ptr));
-	} break;
-
-	case ssaInstr_StructElementPtr: {
-		vmValue address = vm_operand_value(vm, instr->StructElementPtr.address);
-		i32 elem_index  = instr->StructElementPtr.elem_index;
-
-		Type *t = ssa_type(instr->StructElementPtr.address);
-		GB_ASSERT(is_type_pointer(t));
-		i64 offset = vm_type_offset_of(vm, type_deref(t), elem_index);
-		void *ptr = cast(u8 *)address.val_ptr + offset;
-		vm_set_value(f, value, vm_make_value_ptr(t, ptr));
-	} break;
-
-	case ssaInstr_PtrOffset: {
-		Type *t = ssa_type(instr->PtrOffset.address);
-		GB_ASSERT(is_type_pointer(t));
-		i64 elem_size = vm_type_size_of(vm, type_deref(t));
-		vmValue address = vm_operand_value(vm, instr->PtrOffset.address);
-		vmValue offset  = vm_operand_value(vm, instr->PtrOffset.offset);
-
-		void *ptr = cast(u8 *)address.val_ptr + offset.val_int*elem_size;
-		vm_set_value(f, value, vm_make_value_ptr(t, ptr));
-	} break;
-
-	case ssaInstr_Phi: {
-		for_array(i, f->curr_block->preds) {
-			ssaBlock *pred = f->curr_block->preds[i];
-			if (f->prev_block == pred) {
-				vmValue edge = vm_operand_value(vm, instr->Phi.edges[i]);
-				vm_set_value(f, value, edge);
-				break;
-			}
-		}
-	} break;
-
-	case ssaInstr_ArrayExtractValue: {
-		vmValue s = vm_operand_value(vm, instr->ArrayExtractValue.address);
-		vmValue v = s.val_comp[instr->ArrayExtractValue.index];
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_StructExtractValue: {
-		vmValue s = vm_operand_value(vm, instr->StructExtractValue.address);
-		vmValue v = s.val_comp[instr->StructExtractValue.index];
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_Jump: {
-		vm_jump_block(f, instr->Jump.block);
-	} break;
-
-	case ssaInstr_If: {
-		vmValue cond = vm_operand_value(vm, instr->If.cond);
-		if (cond.val_int != 0) {
-			vm_jump_block(f, instr->If.true_block);
-		} else {
-			vm_jump_block(f, instr->If.false_block);
-		}
-	} break;
-
-	case ssaInstr_Return: {
-		Type *return_type = NULL;
-		vmValue result = {0};
-
-		if (instr->Return.value != NULL) {
-			return_type = ssa_type(instr->Return.value);
-			result = vm_operand_value(vm, instr->Return.value);
-		}
-
-		f->result = result;
-		f->curr_block = NULL;
-		f->instr_index = 0;
-		return;
-	} break;
-
-	case ssaInstr_Conv: {
-		// TODO(bill): Assuming little endian
-		vmValue dst = {0};
-		vmValue src = vm_operand_value(vm, instr->Conv.value);
-		i64 from_size = vm_type_size_of(vm, instr->Conv.from);
-		i64 to_size   = vm_type_size_of(vm, instr->Conv.to);
-		switch (instr->Conv.kind) {
-		case ssaConv_trunc:
-			gb_memcopy(&dst, &src, to_size);
-			break;
-		case ssaConv_zext:
-			gb_memcopy(&dst, &src, from_size);
-			break;
-		case ssaConv_fptrunc: {
-			GB_ASSERT(from_size > to_size);
-			GB_ASSERT(base_type(instr->Conv.from) == t_f64);
-			GB_ASSERT(base_type(instr->Conv.to) == t_f32);
-			dst.val_f32 = cast(f32)src.val_f64;
-		} break;
-		case ssaConv_fpext: {
-			GB_ASSERT(from_size < to_size);
-			GB_ASSERT(base_type(instr->Conv.from) == t_f32);
-			GB_ASSERT(base_type(instr->Conv.to) == t_f64);
-			dst.val_f64 = cast(f64)src.val_f32;
-		} break;
-		case ssaConv_fptoui: {
-			Type *from = base_type(instr->Conv.from);
-			if (from == t_f64) {
-				u64 u = cast(u64)src.val_f64;
-				vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, u));
-			} else {
-				u64 u = cast(u64)src.val_f32;
-				vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, u));
-			}
-		} break;
-		case ssaConv_fptosi: {
-			Type *from = base_type(instr->Conv.from);
-			if (from == t_f64) {
-				i64 i = cast(i64)src.val_f64;
-				vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, i));
-			} else {
-				i64 i = cast(i64)src.val_f32;
-				vm_store_integer(vm, &dst, vm_make_value_int(instr->Conv.to, i));
-			}
-		} break;
-		case ssaConv_uitofp: {
-			Type *to = base_type(instr->Conv.to);
-			if (to == t_f64) {
-				dst = vm_make_value_f64(instr->Conv.to, cast(f64)cast(u64)src.val_int);
-			} else {
-				dst = vm_make_value_f32(instr->Conv.to, cast(f32)cast(u64)src.val_int);
-			}
-		} break;
-		case ssaConv_sitofp: {
-			Type *to = base_type(instr->Conv.to);
-			if (to == t_f64) {
-				dst = vm_make_value_f64(instr->Conv.to, cast(f64)cast(i64)src.val_int);
-			} else {
-				dst = vm_make_value_f32(instr->Conv.to, cast(f32)cast(i64)src.val_int);
-			}
-		} break;
-
-		case ssaConv_ptrtoint:
-			dst = vm_make_value_int(instr->Conv.to, cast(i64)src.val_ptr);
-			break;
-		case ssaConv_inttoptr:
-			dst = vm_make_value_ptr(instr->Conv.to, cast(void *)src.val_int);
-			break;
-		case ssaConv_bitcast:
-			dst = src;
-			dst.type = instr->Conv.to;
-			break;
-		}
-
-		vm_set_value(f, value, dst);
-	} break;
-
-	case ssaInstr_Unreachable: {
-		GB_PANIC("Unreachable");
-	} break;
-
-	case ssaInstr_BinaryOp: {
-		ssaInstrBinaryOp *bo = &instr->BinaryOp;
-		Type *type = ssa_type(bo->left);
-		vmValue lhs = vm_operand_value(vm, bo->left);
-		vmValue rhs = vm_operand_value(vm, bo->right);
-		vmValue v = vm_exec_binary_op(vm, type, lhs, rhs, bo->op);
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_Call: {
-		Array<vmValue> args = {0};
-		array_init(&args, f->stack_allocator, instr->Call.arg_count);
-		for (isize i = 0; i < instr->Call.arg_count; i++) {
-			array_add(&args, vm_operand_value(vm, instr->Call.args[i]));
-		}
-		vmValue proc = vm_operand_value(vm, instr->Call.value);
-		if (proc.val_proc.proc != NULL) {
-			vmValue result = vm_call_proc(vm, proc.val_proc.proc, args);
-			vm_set_value(f, value, result);
-		} else {
-			GB_PANIC("TODO(bill): external procedure calls");
-		}
-
-	} break;
-
-	case ssaInstr_Select: {
-		vmValue v = {0};
-		vmValue cond = vm_operand_value(vm, instr->Select.cond);
-		if (cond.val_int != 0) {
-			v = vm_operand_value(vm, instr->Select.true_value);
-		} else {
-			v = vm_operand_value(vm, instr->Select.false_value);
-		}
-
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_VectorExtractElement: {
-		vmValue vector = vm_operand_value(vm, instr->VectorExtractElement.vector);
-		vmValue index  = vm_operand_value(vm, instr->VectorExtractElement.index);
-		vmValue v = vector.val_comp[index.val_int];
-		vm_set_value(f, value, v);
-	} break;
-
-	case ssaInstr_VectorInsertElement: {
-		vmValue vector = vm_operand_value(vm, instr->VectorInsertElement.vector);
-		vmValue elem   = vm_operand_value(vm, instr->VectorInsertElement.elem);
-		vmValue index  = vm_operand_value(vm, instr->VectorInsertElement.index);
-		vector.val_comp[index.val_int] = elem;
-	} break;
-
-	case ssaInstr_VectorShuffle: {
-		ssaValueVectorShuffle *vs = &instr->VectorShuffle;
-		vmValue old_vector = vm_operand_value(vm, instr->VectorShuffle.vector);
-		vmValue new_vector = vm_make_value_comp(ssa_type(value), vm->stack_allocator, vs->index_count);
-
-		for (i32 i = 0; i < vs->index_count; i++) {
-			new_vector.val_comp[i] = old_vector.val_comp[vs->indices[i]];
-		}
-
-		vm_set_value(f, value, new_vector);
-	} break;
-
-	case ssaInstr_BoundsCheck: {
-		ssaInstrBoundsCheck *bc = &instr->BoundsCheck;
-		Array<vmValue> args = {0};
-		array_init(&args, vm->stack_allocator, 5);
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int));
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int));
-		array_add(&args, vm_operand_value(vm, bc->index));
-		array_add(&args, vm_operand_value(vm, bc->len));
-
-		vm_call_proc_by_name(vm, make_string("__bounds_check_error"), args);
-	} break;
-
-	case ssaInstr_SliceBoundsCheck: {
-		ssaInstrSliceBoundsCheck *bc = &instr->SliceBoundsCheck;
-		Array<vmValue> args = {0};
-
-		array_init(&args, vm->stack_allocator, 7);
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.line), t_int));
-		array_add(&args, vm_exact_value(vm, NULL, make_exact_value_integer(bc->pos.column), t_int));
-		array_add(&args, vm_operand_value(vm, bc->low));
-		array_add(&args, vm_operand_value(vm, bc->high));
-		if (!bc->is_substring) {
-			array_add(&args, vm_operand_value(vm, bc->max));
-			vm_call_proc_by_name(vm, make_string("__slice_expr_error"), args);
-		} else {
-			vm_call_proc_by_name(vm, make_string("__substring_expr_error"), args);
-		}
-	} break;
-
-	default: {
-		GB_PANIC("<unknown instr> %d\n", instr->kind);
-	} break;
-	}
-}
-
-
-
-void vm_print_value(vmValue value, Type *type) {
-	type = base_type(type);
-	if (is_type_string(type)) {
-		vmValue data  = value.val_comp[0];
-		vmValue count = value.val_comp[1];
-		gb_printf("`%.*s`", cast(int)count.val_int, cast(u8 *)data.val_ptr);
-	} else if (is_type_boolean(type)) {
-		if (value.val_int != 0) {
-			gb_printf("true");
-		} else {
-			gb_printf("false");
-		}
-	} else if (is_type_integer(type)) {
-		gb_printf("%lld", cast(i64)value.val_int);
-	} else if (type == t_f32) {
-		gb_printf("%f", value.val_f32);
-	} else if (type == t_f64) {
-		gb_printf("%f", value.val_f64);
-	} else if (is_type_pointer(type)) {
-		gb_printf("0x%08x", value.val_ptr);
-	} else if (is_type_array(type)) {
-		gb_printf("[");
-		for_array(i, value.val_comp) {
-			if (i > 0) {
-				gb_printf(", ");
-			}
-			vm_print_value(value.val_comp[i], type->Array.elem);
-		}
-		gb_printf("]");
-	} else if (is_type_vector(type)) {
-		gb_printf("<");
-		for_array(i, value.val_comp) {
-			if (i > 0) {
-				gb_printf(", ");
-			}
-			vm_print_value(value.val_comp[i], type->Vector.elem);
-		}
-		gb_printf(">");
-	} else if (is_type_slice(type)) {
-		gb_printf("[");
-		for_array(i, value.val_comp) {
-			if (i > 0) {
-				gb_printf(", ");
-			}
-			vm_print_value(value.val_comp[i], type->Slice.elem);
-		}
-		gb_printf("]");
-	} else if (is_type_maybe(type)) {
-		if (value.val_comp[1].val_int != 0) {
-			gb_printf("?");
-			vm_print_value(value.val_comp[0], type->Maybe.elem);
-		} else {
-			gb_printf("nil");
-		}
-	} else if (is_type_struct(type)) {
-		if (value.val_comp.count == 0) {
-			gb_printf("nil");
-		} else {
-			gb_printf("{");
-			for_array(i, value.val_comp) {
-				if (i > 0) {
-					gb_printf(", ");
-				}
-				vm_print_value(value.val_comp[i], type->Record.fields[i]->type);
-			}
-			gb_printf("}");
-		}
-	} else if (is_type_tuple(type)) {
-		if (value.val_comp.count != 1) {
-			gb_printf("(");
-		}
-		for_array(i, value.val_comp) {
-			if (i > 0) {
-				gb_printf(", ");
-			}
-			vm_print_value(value.val_comp[i], type->Tuple.variables[i]->type);
-		}
-		if (value.val_comp.count != 1) {
-			gb_printf(")");
-		}
-	}
-}

+ 51 - 55
src/parser.c

@@ -1547,9 +1547,9 @@ void fix_advance_to_next_stmt(AstFile *f) {
 		case Token_defer:
 		case Token_defer:
 		case Token_asm:
 		case Token_asm:
 		case Token_using:
 		case Token_using:
+		case Token_immutable:
 		// case Token_thread_local:
 		// case Token_thread_local:
-		case Token_no_alias:
-		// case Token_immutable:
+		// case Token_no_alias:
 
 
 		case Token_break:
 		case Token_break:
 		case Token_continue:
 		case Token_continue:
@@ -2703,14 +2703,38 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis) {
 	return type;
 	return type;
 }
 }
 
 
-bool is_token_field_prefix(TokenKind kind) {
-	switch (kind) {
+
+typedef enum FieldPrefixKind {
+	FieldPrefix_Invalid,
+
+	FieldPrefix_Using,
+	FieldPrefix_Immutable,
+	FieldPrefix_NoAlias,
+} FieldPrefixKind;
+
+FieldPrefixKind is_token_field_prefix(AstFile *f) {
+	switch (f->curr_token.kind) {
+	case Token_EOF:
+		return FieldPrefix_Invalid;
+
 	case Token_using:
 	case Token_using:
-	case Token_no_alias:
+		return FieldPrefix_Using;
+
 	case Token_immutable:
 	case Token_immutable:
-		return true;
+		return FieldPrefix_Immutable;
+
+	case Token_Hash: {
+		next_token(f);
+		switch (f->curr_token.kind) {
+		case Token_Ident:
+			if (str_eq(f->curr_token.string, str_lit("no_alias"))) {
+				return FieldPrefix_NoAlias;
+			}
+			break;
+		}
+	} break;
 	}
 	}
-	return false;
+	return FieldPrefix_Invalid;
 }
 }
 
 
 
 
@@ -2719,16 +2743,20 @@ u32 parse_field_prefixes(AstFile *f) {
 	i32 no_alias_count  = 0;
 	i32 no_alias_count  = 0;
 	i32 immutable_count = 0;
 	i32 immutable_count = 0;
 
 
-	while (is_token_field_prefix(f->curr_token.kind)) {
-		switch (f->curr_token.kind) {
-		case Token_using:     using_count     += 1; next_token(f); break;
-		case Token_no_alias:  no_alias_count  += 1; next_token(f); break;
-		case Token_immutable: immutable_count += 1; next_token(f); break;
+	for (;;) {
+		FieldPrefixKind kind = is_token_field_prefix(f);
+		if (kind == FieldPrefix_Invalid) {
+			break;
+		}
+		switch (kind) {
+		case FieldPrefix_Using:     using_count     += 1; next_token(f); break;
+		case FieldPrefix_Immutable: immutable_count += 1; next_token(f); break;
+		case FieldPrefix_NoAlias:   no_alias_count  += 1; next_token(f); break;
 		}
 		}
 	}
 	}
 	if (using_count     > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
 	if (using_count     > 1) syntax_error(f->curr_token, "Multiple `using` in this field list");
-	if (no_alias_count  > 1) syntax_error(f->curr_token, "Multiple `no_alias` in this field list");
 	if (immutable_count > 1) syntax_error(f->curr_token, "Multiple `immutable` in this field list");
 	if (immutable_count > 1) syntax_error(f->curr_token, "Multiple `immutable` in this field list");
+	if (no_alias_count  > 1) syntax_error(f->curr_token, "Multiple `#no_alias` in this field list");
 
 
 
 
 	u32 field_flags = 0;
 	u32 field_flags = 0;
@@ -3369,50 +3397,23 @@ AstNode *parse_for_stmt(AstFile *f) {
 }
 }
 
 
 
 
-AstNode *parse_case_clause(AstFile *f) {
+AstNode *parse_case_clause(AstFile *f, bool is_type) {
 	Token token = f->curr_token;
 	Token token = f->curr_token;
 	AstNodeArray list = make_ast_node_array(f);
 	AstNodeArray list = make_ast_node_array(f);
-	if (allow_token(f, Token_case)) {
-		bool prev_allow_range = f->allow_range;
-		f->allow_range = true;
+	expect_token(f, Token_case);
+	bool prev_allow_range = f->allow_range;
+	f->allow_range = !is_type;
+	if (f->curr_token.kind != Token_Colon) {
 		list = parse_rhs_expr_list(f);
 		list = parse_rhs_expr_list(f);
-		f->allow_range = prev_allow_range;
-	} else {
-		expect_token(f, Token_default);
 	}
 	}
+	f->allow_range = prev_allow_range;
 	expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
 	expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
-	// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
 	AstNodeArray stmts = parse_stmt_list(f);
 	AstNodeArray stmts = parse_stmt_list(f);
 
 
 	return ast_case_clause(f, token, list, stmts);
 	return ast_case_clause(f, token, list, stmts);
 }
 }
 
 
 
 
-AstNode *parse_type_case_clause(AstFile *f) {
-	Token token = f->curr_token;
-	AstNodeArray list = make_ast_node_array(f);
-	if (allow_token(f, Token_case)) {
-		for (;;) {
-			AstNode *t = parse_type(f);
-			array_add(&list, t);
-			if (f->curr_token.kind != Token_Comma ||
-			    f->curr_token.kind == Token_EOF) {
-			    break;
-			}
-			next_token(f);
-		}
-	} else {
-		expect_token(f, Token_default);
-	}
-	expect_token(f, Token_Colon); // TODO(bill): Is this the best syntax?
-	// expect_token(f, Token_ArrowRight); // TODO(bill): Is this the best syntax?
-	AstNodeArray stmts = parse_stmt_list(f);
-
-	return ast_case_clause(f, token, list, stmts);
-}
-
-
-
 AstNode *parse_match_stmt(AstFile *f) {
 AstNode *parse_match_stmt(AstFile *f) {
 	if (f->curr_proc == NULL) {
 	if (f->curr_proc == NULL) {
 		syntax_error(f->curr_token, "You cannot use a match statement in the file scope");
 		syntax_error(f->curr_token, "You cannot use a match statement in the file scope");
@@ -3425,6 +3426,7 @@ AstNode *parse_match_stmt(AstFile *f) {
 	AstNode *body = NULL;
 	AstNode *body = NULL;
 	Token open, close;
 	Token open, close;
 	bool is_type_match = false;
 	bool is_type_match = false;
+	AstNodeArray list = make_ast_node_array(f);
 
 
 	if (f->curr_token.kind != Token_OpenBrace) {
 	if (f->curr_token.kind != Token_OpenBrace) {
 		isize prev_level = f->expr_level;
 		isize prev_level = f->expr_level;
@@ -3445,15 +3447,9 @@ AstNode *parse_match_stmt(AstFile *f) {
 		f->expr_level = prev_level;
 		f->expr_level = prev_level;
 	}
 	}
 	open = expect_token(f, Token_OpenBrace);
 	open = expect_token(f, Token_OpenBrace);
-	AstNodeArray list = make_ast_node_array(f);
 
 
-	while (f->curr_token.kind == Token_case ||
-	       f->curr_token.kind == Token_default) {
-		if (is_type_match) {
-			array_add(&list, parse_type_case_clause(f));
-		} else {
-			array_add(&list, parse_case_clause(f));
-		}
+	while (f->curr_token.kind == Token_case) {
+		array_add(&list, parse_case_clause(f, is_type_match));
 	}
 	}
 
 
 	close = expect_token(f, Token_CloseBrace);
 	close = expect_token(f, Token_CloseBrace);
@@ -3863,7 +3859,7 @@ AstNodeArray parse_stmt_list(AstFile *f) {
 	AstNodeArray list = make_ast_node_array(f);
 	AstNodeArray list = make_ast_node_array(f);
 
 
 	while (f->curr_token.kind != Token_case &&
 	while (f->curr_token.kind != Token_case &&
-	       f->curr_token.kind != Token_default &&
+	       // f->curr_token.kind != Token_default &&
 	       f->curr_token.kind != Token_CloseBrace &&
 	       f->curr_token.kind != Token_CloseBrace &&
 	       f->curr_token.kind != Token_EOF) {
 	       f->curr_token.kind != Token_EOF) {
 		AstNode *stmt = parse_stmt(f);
 		AstNode *stmt = parse_stmt(f);

+ 27 - 27
src/ssa.c

@@ -1051,9 +1051,9 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 		AstNode *sel = unparen_expr(se->selector);
 		AstNode *sel = unparen_expr(se->selector);
 		if (sel->kind == AstNode_Ident) {
 		if (sel->kind == AstNode_Ident) {
 			String selector = sel->Ident.string;
 			String selector = sel->Ident.string;
-			TypeAndValue *tav = type_and_value_of_expression(p->module->info, se->expr);
+			TypeAndValue tav = type_and_value_of_expr(p->module->info, se->expr);
 
 
-			if (tav == NULL) {
+			if (tav.mode == Addressing_Invalid) {
 				// NOTE(bill): Imports
 				// NOTE(bill): Imports
 				Entity *imp = entity_of_ident(p->module->info, se->expr);
 				Entity *imp = entity_of_ident(p->module->info, se->expr);
 				if (imp != NULL) {
 				if (imp != NULL) {
@@ -1063,8 +1063,8 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 			}
 			}
 
 
 
 
-			Type *type = base_type(tav->type);
-			if (tav->mode == Addressing_Type) { // Addressing_Type
+			Type *type = base_type(tav.type);
+			if (tav.mode == Addressing_Type) { // Addressing_Type
 				GB_PANIC("TODO: SelectorExpr Addressing_Type");
 				GB_PANIC("TODO: SelectorExpr Addressing_Type");
 				// Selection sel = lookup_field(p->allocator, type, selector, true);
 				// Selection sel = lookup_field(p->allocator, type, selector, true);
 				// Entity *e = sel.entity;
 				// Entity *e = sel.entity;
@@ -1099,7 +1099,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
 		} else {
 		} else {
 			Type *type = base_type(type_of_expr(p->module->info, se->expr));
 			Type *type = base_type(type_of_expr(p->module->info, se->expr));
 			GB_ASSERT(is_type_integer(type));
 			GB_ASSERT(is_type_integer(type));
-			ExactValue val = type_and_value_of_expression(p->module->info, sel)->value;
+			ExactValue val = type_and_value_of_expr(p->module->info, sel).value;
 			i64 index = val.value_integer;
 			i64 index = val.value_integer;
 
 
 			Selection sel = lookup_field_from_index(p->allocator, type, index);
 			Selection sel = lookup_field_from_index(p->allocator, type, index);
@@ -1635,43 +1635,43 @@ ssaValue *ssa_emit_logical_binary_expr(ssaProc *p, AstNode *expr) {
 ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 	expr = unparen_expr(expr);
 	expr = unparen_expr(expr);
 
 
-	TypeAndValue *tv = map_tav_get(&p->module->info->types, hash_pointer(expr));
-	GB_ASSERT_NOT_NULL(tv);
+	TypeAndValue tv = type_and_value_of_expr(p->module->info, expr);
+	GB_ASSERT(tv.mode != Addressing_Invalid);
 
 
-	if (tv->value.kind != ExactValue_Invalid) {
-		Type *t = core_type(tv->type);
+	if (tv.value.kind != ExactValue_Invalid) {
+		Type *t = core_type(tv.type);
 		if (is_type_boolean(t)) {
 		if (is_type_boolean(t)) {
-			return ssa_const_bool(p, tv->type, tv->value.value_bool);
+			return ssa_const_bool(p, tv.type, tv.value.value_bool);
 		} else if (is_type_string(t)) {
 		} else if (is_type_string(t)) {
-			GB_ASSERT(tv->value.kind == ExactValue_String);
-			return ssa_const_string(p, tv->type, tv->value.value_string);
+			GB_ASSERT(tv.value.kind == ExactValue_String);
+			return ssa_const_string(p, tv.type, tv.value.value_string);
 		} else if(is_type_slice(t)) {
 		} else if(is_type_slice(t)) {
-			return ssa_const_slice(p, tv->type, tv->value);
+			return ssa_const_slice(p, tv.type, tv.value);
 		} else if (is_type_integer(t)) {
 		} else if (is_type_integer(t)) {
-			GB_ASSERT(tv->value.kind == ExactValue_Integer);
+			GB_ASSERT(tv.value.kind == ExactValue_Integer);
 
 
 			i64 s = 8*type_size_of(p->allocator, t);
 			i64 s = 8*type_size_of(p->allocator, t);
 			switch (s) {
 			switch (s) {
-			case 8:  return ssa_const_i8 (p, tv->type, tv->value.value_integer);
-			case 16: return ssa_const_i16(p, tv->type, tv->value.value_integer);
-			case 32: return ssa_const_i32(p, tv->type, tv->value.value_integer);
-			case 64: return ssa_const_i64(p, tv->type, tv->value.value_integer);
+			case 8:  return ssa_const_i8 (p, tv.type, tv.value.value_integer);
+			case 16: return ssa_const_i16(p, tv.type, tv.value.value_integer);
+			case 32: return ssa_const_i32(p, tv.type, tv.value.value_integer);
+			case 64: return ssa_const_i64(p, tv.type, tv.value.value_integer);
 			default: GB_PANIC("Unknown integer size");
 			default: GB_PANIC("Unknown integer size");
 			}
 			}
 		} else if (is_type_float(t)) {
 		} else if (is_type_float(t)) {
-			GB_ASSERT(tv->value.kind == ExactValue_Float);
+			GB_ASSERT(tv.value.kind == ExactValue_Float);
 			i64 s = 8*type_size_of(p->allocator, t);
 			i64 s = 8*type_size_of(p->allocator, t);
 			switch (s) {
 			switch (s) {
-			case 32: return ssa_const_f32(p, tv->type, tv->value.value_float);
-			case 64: return ssa_const_f64(p, tv->type, tv->value.value_float);
+			case 32: return ssa_const_f32(p, tv.type, tv.value.value_float);
+			case 64: return ssa_const_f64(p, tv.type, tv.value.value_float);
 			default: GB_PANIC("Unknown float size");
 			default: GB_PANIC("Unknown float size");
 			}
 			}
 		}
 		}
 		// IMPORTANT TODO(bill): Do constant record/array literals correctly
 		// IMPORTANT TODO(bill): Do constant record/array literals correctly
-		return ssa_const_nil(p, tv->type);
+		return ssa_const_nil(p, tv.type);
 	}
 	}
 
 
-	if (tv->mode == Addressing_Variable) {
+	if (tv.mode == Addressing_Variable) {
 		return ssa_addr_load(p, ssa_build_addr(p, expr));
 		return ssa_addr_load(p, ssa_build_addr(p, expr));
 	}
 	}
 
 
@@ -1716,12 +1716,12 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 			return ssa_build_addr(p, ue->expr).addr;
 			return ssa_build_addr(p, ue->expr).addr;
 		}
 		}
 		ssaValue *x = ssa_build_expr(p, ue->expr);
 		ssaValue *x = ssa_build_expr(p, ue->expr);
-		return ssa_emit_unary_arith(p, ue->op.kind, x, tv->type);
+		return ssa_emit_unary_arith(p, ue->op.kind, x, tv.type);
 
 
 	case_end;
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, expr);
 	case_ast_node(be, BinaryExpr, expr);
-		Type *type = default_type(tv->type);
+		Type *type = default_type(tv.type);
 
 
 		switch (be->op.kind) {
 		switch (be->op.kind) {
 		case Token_Add:
 		case Token_Add:
@@ -1803,7 +1803,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 		ssa_emit_jump(p, done);
 		ssa_emit_jump(p, done);
 		ssa_start_block(p, done);
 		ssa_start_block(p, done);
 
 
-		return ssa_new_value2(p, ssaOp_Phi, tv->type, yes, no);
+		return ssa_new_value2(p, ssaOp_Phi, tv.type, yes, no);
 	case_end;
 	case_end;
 
 
 
 
@@ -1840,7 +1840,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
 		if (map_tav_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
 		if (map_tav_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
 			GB_ASSERT(ce->args.count == 1);
 			GB_ASSERT(ce->args.count == 1);
 			ssaValue *x = ssa_build_expr(p, ce->args.e[0]);
 			ssaValue *x = ssa_build_expr(p, ce->args.e[0]);
-			return ssa_emit_conv(p, x, tv->type);
+			return ssa_emit_conv(p, x, tv.type);
 		}
 		}
 
 
 		AstNode *p = unparen_expr(ce->proc);
 		AstNode *p = unparen_expr(ce->proc);

+ 0 - 3
src/tokenizer.c

@@ -88,14 +88,12 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_for,            "for"),                 \
 	TOKEN_KIND(Token_for,            "for"),                 \
 	TOKEN_KIND(Token_in,             "in"),                  \
 	TOKEN_KIND(Token_in,             "in"),                  \
 	TOKEN_KIND(Token_match,          "match"),               \
 	TOKEN_KIND(Token_match,          "match"),               \
-	TOKEN_KIND(Token_default,        "default"),             \
 	TOKEN_KIND(Token_case,           "case"),                \
 	TOKEN_KIND(Token_case,           "case"),                \
 	TOKEN_KIND(Token_break,          "break"),               \
 	TOKEN_KIND(Token_break,          "break"),               \
 	TOKEN_KIND(Token_continue,       "continue"),            \
 	TOKEN_KIND(Token_continue,       "continue"),            \
 	TOKEN_KIND(Token_fallthrough,    "fallthrough"),         \
 	TOKEN_KIND(Token_fallthrough,    "fallthrough"),         \
 	TOKEN_KIND(Token_defer,          "defer"),               \
 	TOKEN_KIND(Token_defer,          "defer"),               \
 	TOKEN_KIND(Token_return,         "return"),              \
 	TOKEN_KIND(Token_return,         "return"),              \
-	TOKEN_KIND(Token_give,           "give"),                \
 	TOKEN_KIND(Token_proc,           "proc"),                \
 	TOKEN_KIND(Token_proc,           "proc"),                \
 	TOKEN_KIND(Token_macro,          "macro"),               \
 	TOKEN_KIND(Token_macro,          "macro"),               \
 	TOKEN_KIND(Token_struct,         "struct"),              \
 	TOKEN_KIND(Token_struct,         "struct"),              \
@@ -107,7 +105,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
 	TOKEN_KIND(Token_dynamic,        "dynamic"),             \
 	TOKEN_KIND(Token_dynamic,        "dynamic"),             \
 	TOKEN_KIND(Token_map,            "map"),                 \
 	TOKEN_KIND(Token_map,            "map"),                 \
 	TOKEN_KIND(Token_using,          "using"),               \
 	TOKEN_KIND(Token_using,          "using"),               \
-	TOKEN_KIND(Token_no_alias,       "no_alias"),            \
 	TOKEN_KIND(Token_immutable,      "immutable"),           \
 	TOKEN_KIND(Token_immutable,      "immutable"),           \
 	TOKEN_KIND(Token_context,        "context"),             \
 	TOKEN_KIND(Token_context,        "context"),             \
 	TOKEN_KIND(Token_push_context,   "push_context"),        \
 	TOKEN_KIND(Token_push_context,   "push_context"),        \

+ 2 - 2
src/types.c

@@ -36,7 +36,7 @@ typedef enum BasicKind {
 	Basic_UntypedRune,
 	Basic_UntypedRune,
 	Basic_UntypedNil,
 	Basic_UntypedNil,
 
 
-	Basic_Count,
+	Basic_COUNT,
 
 
 	Basic_byte = Basic_u8,
 	Basic_byte = Basic_u8,
 	Basic_rune = Basic_i32,
 	Basic_rune = Basic_i32,
@@ -290,10 +290,10 @@ gb_global Type *t_untyped_quaternion = &basic_types[Basic_UntypedQuaternion];
 gb_global Type *t_untyped_string     = &basic_types[Basic_UntypedString];
 gb_global Type *t_untyped_string     = &basic_types[Basic_UntypedString];
 gb_global Type *t_untyped_rune       = &basic_types[Basic_UntypedRune];
 gb_global Type *t_untyped_rune       = &basic_types[Basic_UntypedRune];
 gb_global Type *t_untyped_nil        = &basic_types[Basic_UntypedNil];
 gb_global Type *t_untyped_nil        = &basic_types[Basic_UntypedNil];
+
 gb_global Type *t_byte               = &basic_type_aliases[0];
 gb_global Type *t_byte               = &basic_type_aliases[0];
 gb_global Type *t_rune               = &basic_type_aliases[1];
 gb_global Type *t_rune               = &basic_type_aliases[1];
 
 
-
 gb_global Type *t_u8_ptr  = NULL;
 gb_global Type *t_u8_ptr  = NULL;
 gb_global Type *t_int_ptr = NULL;
 gb_global Type *t_int_ptr = NULL;
 gb_global Type *t_i64_ptr = NULL;
 gb_global Type *t_i64_ptr = NULL;