Browse Source

`make` as a user-level procedure rather than a built-in procedure

gingerBill 7 years ago
parent
commit
835d7dcab2
5 changed files with 82 additions and 863 deletions
  1. 28 0
      core/mem/alloc.odin
  2. 9 0
      core/runtime/core.odin
  3. 45 439
      src/check_expr.cpp
  4. 0 24
      src/checker.hpp
  5. 0 400
      src/ir.cpp

+ 28 - 0
core/mem/alloc.odin

@@ -102,6 +102,34 @@ new_clone_with_allocator :: inline proc(a: Allocator, data: $T, loc := #caller_l
 }
 
 
+make_slice :: proc(T: type/[]$E, len: int) -> T {
+	data := alloc(size_of(E)*len, align_of(E));
+	s := Raw_Slice{data, len};
+	return transmute(T)s;
+}
+make_dynamic_array_len :: proc(T: type/[dynamic]$E, len: int = 16) -> T {
+	return make_dynamic_array(T, len, len);
+}
+make_dynamic_array :: proc(T: type/[dynamic]$E, len, cap: int) -> T {
+	data := alloc(size_of(E)*cap, align_of(E));
+	s := Raw_Dynamic_Array{data, len, cap, context.allocator};
+	return transmute(T)s;
+}
+make_map :: proc(T: type/map[$K]$E, cap: int = 16) -> T {
+	m: T;
+	reserve_map(&m, cap);
+	return m;
+}
+
+make :: proc[
+	make_slice,
+	make_dynamic_array_len,
+	make_dynamic_array,
+	make_map,
+];
+
+
+
 default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, loc := #caller_location) -> rawptr {
 	if old_memory == nil do return alloc(new_size, alignment, loc);
 

+ 9 - 0
core/runtime/core.odin

@@ -325,6 +325,15 @@ delete :: proc[
 	mem.delete_map,
 ];
 
+@(builtin)
+make :: proc[
+	mem.make_slice,
+	mem.make_dynamic_array_len,
+	mem.make_dynamic_array,
+	mem.make_map,
+];
+
+
 
 
 @(builtin)

+ 45 - 439
src/check_expr.cpp

@@ -2794,8 +2794,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 	}
 
 	switch (id) {
-	// case BuiltinProc_new:
-	case BuiltinProc_make:
 	case BuiltinProc_size_of:
 	case BuiltinProc_align_of:
 	case BuiltinProc_offset_of:
@@ -2933,294 +2931,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 		break;
 	}
 
-	#if 0
-	case BuiltinProc_new: {
-		// new :: proc(Type) -> ^Type
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = op.type;
-		if ((op.mode != Addressing_Type && type == nullptr) || type == t_invalid) {
-			error(ce->args[0], "Expected a type for 'new'");
-			return false;
-		}
-		operand->mode = Addressing_Value;
-		operand->type = alloc_type_pointer(type);
-
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_new_slice: {
-		// new_slice :: proc(Type, len: int) -> []Type
-		// proc new_slice(Type, len, cap: int) -> []Type
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = op.type;
-		if ((op.mode != Addressing_Type && type == nullptr) || type == t_invalid) {
-			error(ce->args[0], "Expected a type for 'new_slice'");
-			return false;
-		}
-
-		isize arg_count = ce->args.count;
-		if (arg_count < 2 || 3 < arg_count) {
-			error(ce->args[0], "'new_slice' expects 2 or 3 arguments, found %td", arg_count);
-			// NOTE(bill): Return the correct type to reduce errors
-		} else {
-			// If any are constant
-			i64 sizes[2] = {};
-			isize size_count = 0;
-			for (isize i = 1; i < arg_count; i++) {
-				i64 val = 0;
-				bool ok = check_index_value(c, ce->args[i], -1, &val);
-				if (ok && val >= 0) {
-					GB_ASSERT(size_count < gb_count_of(sizes));
-					sizes[size_count++] = val;
-				}
-			}
-
-			if (size_count == 2 && sizes[0] > sizes[1]) {
-				error(ce->args[1], "'new_slice' count and capacity are swapped");
-				// No need quit
-			}
-		}
-
-		operand->mode = Addressing_Value;
-		operand->type = alloc_type_slice(type);
-
-		break;
-	}
-	#endif
-	case BuiltinProc_make: {
-		// make :: proc(Type, len: int) -> Type
-		// proc make(Type, len, cap: int) -> Type
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = op.type;
-		if ((op.mode != Addressing_Type && type == nullptr) || type == t_invalid) {
-			error(ce->args[0], "Expected a type for 'make'");
-			return false;
-		}
-
-		isize min_args = 0;
-		isize max_args = 1;
-		if (is_type_slice(type)) {
-			min_args = 2;
-			max_args = 2;
-			add_package_dependency(c, "mem", "alloc");
-		} else if (is_type_map(type)) {
-			min_args = 1;
-			max_args = 2;
-			add_package_dependency(c, "runtime", "__dynamic_map_reserve");
-		} else if (is_type_dynamic_array(type)) {
-			min_args = 1;
-			max_args = 3;
-			add_package_dependency(c, "runtime", "__dynamic_array_make");
-		} else {
-			gbString str = type_to_string(type);
-			error(call, "Cannot 'make' %s; type must be a slice, map, or dynamic array", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		isize arg_count = ce->args.count;
-		if (arg_count < min_args || max_args < arg_count) {
-			error(ce->args[0], "'make' expects %td or %d argument, found %td", min_args, max_args, arg_count);
-			return false;
-		}
-
-		// If any are constant
-		i64 sizes[4] = {};
-		isize size_count = 0;
-		for (isize i = 1; i < arg_count; i++) {
-			i64 val = 0;
-			bool ok = check_index_value(c, false, ce->args[i], -1, &val);
-			if (ok && val >= 0) {
-				GB_ASSERT(size_count < gb_count_of(sizes));
-				sizes[size_count++] = val;
-			}
-		}
-
-		if (size_count == 2 && sizes[0] > sizes[1]) {
-			error(ce->args[1], "'make' count and capacity are swapped");
-			// No need quit
-		}
-
-		operand->mode = Addressing_Value;
-		operand->type = type;
-
-		break;
-	}
-
-	#if 0
-	case BuiltinProc_free: {
-		// free :: proc(^Type)
-		// proc free([]Type)
-		// proc free(string)
-		// proc free(map[K]T)
-		Type *type = operand->type;
-		bool ok = false;
-		if (is_type_pointer(type)) {
-			ok = true;
-		} else if (is_type_slice(type)) {
-			ok = true;
-		} else if (is_type_string(type)) {
-			ok = true;
-		} else if (is_type_dynamic_array(type)) {
-			ok = true;
-		} else if (is_type_dynamic_map(type)) {
-			ok = true;
-		}
-
-		if (!ok) {
-			gbString type_str = type_to_string(type);
-			error(operand->expr, "Invalid type for 'free', got '%s'", type_str);
-			gb_string_free(type_str);
-			return false;
-		}
-
-
-		operand->mode = Addressing_NoValue;
-
-		break;
-	}
-	#endif
-
-
-	#if 0
-	case BuiltinProc_reserve: {
-		// reserve :: proc([dynamic]Type, count: int) {
-		// reserve :: proc(map[Key]Type, count: int) {
-		Type *type = operand->type;
-		if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) {
-			gbString str = type_to_string(type);
-			error(operand->expr, "Expected a dynamic array or dynamic map, got '%s'", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		Ast *capacity = ce->args[1];
-		Operand op = {};
-		check_expr(c, &op, capacity);
-		if (op.mode == Addressing_Invalid) {
-			return false;
-		}
-		Type *arg_type = base_type(op.type);
-		if (!is_type_integer(arg_type)) {
-			error(operand->expr, "'reserve' capacities must be an integer");
-			return false;
-		}
-
-		operand->type = nullptr;
-		operand->mode = Addressing_NoValue;
-
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_clear: {
-		Type *type = operand->type;
-		bool is_pointer = is_type_pointer(type);
-		type = base_type(type_deref(type));
-		if (!is_type_dynamic_array(type) && !is_type_map(type) && !is_type_slice(type)) {
-			gbString str = type_to_string(type);
-			error(operand->expr, "Invalid type for 'clear', got '%s'", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		operand->type = nullptr;
-		operand->mode = Addressing_NoValue;
-
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_append: {
-		// append :: proc([dynamic]Type, item: ..Type)
-		// proc append([]Type, item: ..Type)
-		Operand prev_operand = *operand;
-
-		Type *type = operand->type;
-		bool is_pointer = is_type_pointer(type);
-		type = base_type(type_deref(type));
-		if (!is_type_dynamic_array(type) && !is_type_slice(type)) {
-			gbString str = type_to_string(type);
-			error(operand->expr, "Expected a slice or dynamic array, got '%s'", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		bool is_addressable = operand->mode == Addressing_Variable;
-		if (is_pointer) {
-			is_addressable = true;
-		}
-		if (!is_addressable) {
-			error(operand->expr, "'append' can only operate on addressable values");
-			return false;
-		}
-
-		Type *elem = nullptr;
-		if (is_type_dynamic_array(type)) {
-			elem = type->DynamicArray.elem;
-		} else {
-			elem = type->Slice.elem;
-		}
-		Type *slice_elem = alloc_type_slice(elem);
-
-		Type *proc_type_params = alloc_type_tuple(c->allocator);
-		proc_type_params->Tuple.variables = gb_alloc_array(c->allocator, Entity *, 2);
-		proc_type_params->Tuple.variable_count = 2;
-		proc_type_params->Tuple.variables[0] = alloc_entity_param(c->allocator, nullptr, blank_token, operand->type, false, false);
-		proc_type_params->Tuple.variables[1] = alloc_entity_param(c->allocator, nullptr, blank_token, slice_elem, false, false);
-		Type *proc_type = alloc_type_proc(nullptr, proc_type_params, 2, nullptr, false, true, ProcCC_Odin);
-
-		check_call_arguments(c, &prev_operand, proc_type, call);
-
-		if (prev_operand.mode == Addressing_Invalid) {
-			return false;
-		}
-		operand->mode = Addressing_Value;
-		operand->type = t_int;
-
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_delete: {
-		// delete :: proc(map[Key]Value, key: Key)
-		Type *type = operand->type;
-		if (!is_type_map(type)) {
-			gbString str = type_to_string(type);
-			error(operand->expr, "Expected a map, got '%s'", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		Type *key = base_type(type)->Map.key;
-		Operand x = {Addressing_Invalid};
-		Ast *key_node = ce->args[1];
-		Operand op = {};
-		check_expr(c, &op, key_node);
-		if (op.mode == Addressing_Invalid) {
-			return false;
-		}
-
-		if (!check_is_assignable_to(c, &op, key)) {
-			gbString kt = type_to_string(key);
-			gbString ot = type_to_string(op.type);
-			error(operand->expr, "Expected a key of type '%s', got '%s'", key, ot);
-			gb_string_free(ot);
-			gb_string_free(kt);
-			return false;
-		}
-
-		operand->mode = Addressing_NoValue;
-
-		break;
-	}
-	#endif
-
-
 	case BuiltinProc_size_of: {
 		// size_of :: proc(Type or expr) -> untyped int
 		Operand o = {};
@@ -3604,72 +3314,9 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
 			return false;
 		}
 
-
-break;
-	}
-
-	#if 0
-	case BuiltinProc_slice_ptr: {
-		// slice_ptr :: proc(a: ^T, len: int) -> []T
-		// proc slice_ptr(a: ^T, len, cap: int) -> []T
-		// ^T cannot be rawptr
-		Type *ptr_type = base_type(operand->type);
-		if (!is_type_pointer(ptr_type)) {
-			gbString type_str = type_to_string(operand->type);
-			error(call, "Expected a pointer to 'slice_ptr', got '%s'", type_str);
-			gb_string_free(type_str);
-			return false;
-		}
-
-		if (ptr_type == t_rawptr) {
-			error(call, "'rawptr' cannot have pointer arithmetic");
-			return false;
-		}
-
-		isize arg_count = ce->args.count;
-		if (arg_count < 2 || 3 < arg_count) {
-			error(ce->args[0], "'slice_ptr' expects 2 or 3 arguments, found %td", arg_count);
-			// NOTE(bill): Return the correct type to reduce errors
-		} else {
-			// If any are constant
-			i64 sizes[2] = {};
-			isize size_count = 0;
-			for (isize i = 1; i < arg_count; i++) {
-				i64 val = 0;
-				bool ok = check_index_value(c, false, ce->args[i], -1, &val);
-				if (ok && val >= 0) {
-					GB_ASSERT(size_count < gb_count_of(sizes));
-					sizes[size_count++] = val;
-				}
-			}
-
-			if (size_count == 2 && sizes[0] > sizes[1]) {
-				error(ce->args[1], "'slice_ptr' count and capacity are swapped");
-				// No need quit
-			}
-		}
-		operand->type = alloc_type_slice(ptr_type->Pointer.elem);
-		operand->mode = Addressing_Value;
-
 		break;
 	}
 
-	case BuiltinProc_slice_to_bytes: {
-		// slice_to_bytes :: proc(a: []T) -> []u8
-		Type *slice_type = base_type(operand->type);
-		if (!is_type_slice(slice_type)) {
-			gbString type_str = type_to_string(operand->type);
-			error(call, "Expected a slice type, got '%s'", type_str);
-			gb_string_free(type_str);
-			return false;
-		}
-
-		operand->type = t_u8_slice;
-		operand->mode = Addressing_Value;
-
-		break;
-	}
-	#endif
 	case BuiltinProc_expand_to_tuple: {
 		Type *type = base_type(operand->type);
 		if (!is_type_struct(type) && !is_type_array(type)) {
@@ -3773,7 +3420,7 @@ break;
 		}
 
 
-break;
+		break;
 	}
 
 	case BuiltinProc_max: {
@@ -3849,7 +3496,7 @@ break;
 		}
 
 
-break;
+		break;
 	}
 
 	case BuiltinProc_abs: {
@@ -4002,59 +3649,6 @@ break;
 		break;
 	}
 
-	#if 0
-	case BuiltinProc_transmute: {
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *t = op.type;
-		if ((op.mode != Addressing_Type && t == nullptr) || t == t_invalid) {
-			error(ce->args[0], "Expected a type for 'transmute'");
-			return false;
-		}
-		Ast *expr = ce->args[1];
-		Operand *o = operand;
-		check_expr(c, o, expr);
-		if (o->mode == Addressing_Invalid) {
-			return false;
-		}
-
-		if (o->mode == Addressing_Constant) {
-			gbString expr_str = expr_to_string(o->expr);
-			error(o->expr, "Cannot transmute a constant expression: '%s'", expr_str);
-			gb_string_free(expr_str);
-			o->mode = Addressing_Invalid;
-			o->expr = expr;
-			return false;
-		}
-
-		if (is_type_untyped(o->type)) {
-			gbString expr_str = expr_to_string(o->expr);
-			error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str);
-			gb_string_free(expr_str);
-			o->mode = Addressing_Invalid;
-			o->expr = expr;
-			return false;
-		}
-
-		i64 srcz = type_size_of(o->type);
-		i64 dstz = type_size_of(t);
-		if (srcz != dstz) {
-			gbString expr_str = expr_to_string(o->expr);
-			gbString type_str = type_to_string(t);
-			error(o->expr, "Cannot transmute '%s' to '%s', %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
-			gb_string_free(type_str);
-			gb_string_free(expr_str);
-			o->mode = Addressing_Invalid;
-			o->expr = expr;
-			return false;
-		}
-
-		o->mode = Addressing_Value;
-		o->type = t;
-
-		break;
-	}
-	#endif
 	}
 
 	return true;
@@ -4246,6 +3840,8 @@ CALL_ARGUMENT_CHECKER(check_call_arguments_internal) {
 					gen_entity = poly_proc_data.gen_entity;
 					GB_ASSERT(is_type_proc(gen_entity->type));
 					final_proc_type = gen_entity->type;
+				} else {
+					err = CallArgumentError_WrongTypes;
 				}
 			}
 
@@ -4614,44 +4210,54 @@ CallArgumentData check_call_arguments(CheckerContext *c, Operand *operand, Type
 
 
 		if (valid_count == 0) {
-			error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name);
-			gb_printf_err("\tGiven argument types: (");
+			bool all_invalid_type = true;
 			for_array(i, operands) {
 				Operand o = operands[i];
-				if (i > 0) gb_printf_err(", ");
-				gbString type = type_to_string(o.type);
-				defer (gb_string_free(type));
-				gb_printf_err("%s", type);
+				if (o.type != t_invalid)  {
+					all_invalid_type = false;
+					break;
+				}
 			}
-			gb_printf_err(")\n");
+			if (!all_invalid_type) {
+				error(operand->expr, "No procedures or ambiguous call for procedure group '%s' that match with the given arguments", expr_name);
+				gb_printf_err("\tGiven argument types: (");
+				for_array(i, operands) {
+					Operand o = operands[i];
+					if (i > 0) gb_printf_err(", ");
+					gbString type = type_to_string(o.type);
+					defer (gb_string_free(type));
+					gb_printf_err("%s", type);
+				}
+				gb_printf_err(")\n");
 
-			if (procs.count > 0) {
-				gb_printf_err("Did you mean to use one of the following:\n");
-			}
-			for_array(i, procs) {
-				Entity *proc = procs[i];
-				TokenPos pos = proc->token.pos;
-				Type *t = base_type(proc->type);
-				if (t == t_invalid) continue;
-				GB_ASSERT(t->kind == Type_Proc);
-				gbString pt;
-				defer (gb_string_free(pt));
-				if (t->Proc.node != nullptr) {
-					pt = expr_to_string(t->Proc.node);
-				} else {
-					pt = type_to_string(t);
+				if (procs.count > 0) {
+					gb_printf_err("Did you mean to use one of the following:\n");
 				}
-				String name = proc->token.string;
+				for_array(i, procs) {
+					Entity *proc = procs[i];
+					TokenPos pos = proc->token.pos;
+					Type *t = base_type(proc->type);
+					if (t == t_invalid) continue;
+					GB_ASSERT(t->kind == Type_Proc);
+					gbString pt;
+					defer (gb_string_free(pt));
+					if (t->Proc.node != nullptr) {
+						pt = expr_to_string(t->Proc.node);
+					} else {
+						pt = type_to_string(t);
+					}
+					String name = proc->token.string;
 
-				char const *sep = "::";
-				if (proc->kind == Entity_Variable) {
-					sep = ":=";
+					char const *sep = "::";
+					if (proc->kind == Entity_Variable) {
+						sep = ":=";
+					}
+					// gb_printf_err("\t%.*s %s %s at %.*s(%td:%td) with score %lld\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
+					gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column);
+				}
+				if (procs.count > 0) {
+					gb_printf_err("\n");
 				}
-				// gb_printf_err("\t%.*s %s %s at %.*s(%td:%td) with score %lld\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column, cast(long long)valids[i].score);
-				gb_printf_err("\t%.*s %s %s at %.*s(%td:%td)\n", LIT(name), sep, pt, LIT(pos.file), pos.line, pos.column);
-			}
-			if (procs.count > 0) {
-				gb_printf_err("\n");
 			}
 			result_type = t_invalid;
 		} else if (valid_count > 1) {

+ 0 - 24
src/checker.hpp

@@ -58,15 +58,6 @@ enum BuiltinProcId {
 	BuiltinProc_len,
 	BuiltinProc_cap,
 
-	// BuiltinProc_new,
-	BuiltinProc_make,
-	// BuiltinProc_free,
-
-	// BuiltinProc_reserve,
-	// BuiltinProc_clear,
-	// BuiltinProc_append,
-	// BuiltinProc_delete,
-
 	BuiltinProc_size_of,
 	BuiltinProc_align_of,
 	BuiltinProc_offset_of,
@@ -81,9 +72,6 @@ enum BuiltinProcId {
 	BuiltinProc_imag,
 	BuiltinProc_conj,
 
-	// BuiltinProc_slice_ptr,
-	// BuiltinProc_slice_to_bytes,
-
 	BuiltinProc_expand_to_tuple,
 
 	BuiltinProc_min,
@@ -101,15 +89,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("len"),              1, false, Expr_Expr},
 	{STR_LIT("cap"),              1, false, Expr_Expr},
 
-	// {STR_LIT("new"),              1, false, 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("clear"),            1, false, Expr_Stmt},
-	// {STR_LIT("append"),           1, true,  Expr_Expr},
-	// {STR_LIT("delete"),           2, false, Expr_Stmt},
-
 	{STR_LIT("size_of"),          1, false, Expr_Expr},
 	{STR_LIT("align_of"),         1, false, Expr_Expr},
 	{STR_LIT("offset_of"),        2, false, Expr_Expr},
@@ -124,9 +103,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("imag"),             1, false, Expr_Expr},
 	{STR_LIT("conj"),             1, false, Expr_Expr},
 
-	// {STR_LIT("slice_ptr"),        2, true,  Expr_Expr},
-	// {STR_LIT("slice_to_bytes"),   1, false, Expr_Expr},
-
 	{STR_LIT("expand_to_tuple"),  1, false, Expr_Expr},
 
 	{STR_LIT("min"),              2, false, Expr_Expr},

+ 0 - 400
src/ir.cpp

@@ -4424,406 +4424,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, Ast *expr, TypeAndValue tv, Bu
 		break;
 	}
 
-	#if 0
-	case BuiltinProc_new: {
-		ir_emit_comment(proc, str_lit("new"));
-		// proc new(Type) -> ^Type
-		gbAllocator a = ir_allocator();
-
-		Type *type = type_of_expr(ce->args[0]);
-		Type *allocation_type = type;
-		i32 variant_index = 0;
-		if (is_type_struct(type)) {
-			Type *st = base_type(type);
-			if (st->Struct.variant_parent != nullptr) {
-				allocation_type = st->Struct.variant_parent;
-				variant_index = st->Struct.variant_index;
-				GB_ASSERT(allocation_type != nullptr);
-			}
-		}
-		Type *ptr_type = alloc_type_pointer(type);
-
-		i64 size  = type_size_of(allocation_type);
-		i64 align = type_align_of(allocation_type);
-
-		irValue **args = gb_alloc_array(a, irValue *, 2);
-		args[0] = ir_const_int(size);
-		args[1] = ir_const_int(align);
-		irValue *call = ir_emit_runtime_call(proc, "alloc", args, 2);
-		irValue *v = ir_emit_conv(proc, call, ptr_type);
-		if (type != allocation_type) {
-			Type *u = base_type(allocation_type);
-			Type *uptr_type = alloc_type_pointer(u);
-			irValue *parent = ir_emit_conv(proc, call, uptr_type);
-			irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
-			ir_emit_store(proc, tag_ptr, ir_const_int(variant_index));
-		}
-		return v;
-		break;
-	}
-	#endif
-
-	case BuiltinProc_make: {
-		ir_emit_comment(proc, str_lit("make"));
-		gbAllocator a = ir_allocator();
-		Type *type = type_of_expr(ce->args[0]);
-
-		String proc_name = {};
-		if (proc->entity != nullptr) {
-			proc_name = proc->entity->token.string;
-		}
-
-		if (is_type_slice(type)) {
-			Type *elem_type = core_type(type)->Slice.elem;
-			Type *elem_ptr_type = alloc_type_pointer(elem_type);
-
-			i64 esz = type_size_of(elem_type);
-			i64 eal = type_align_of(elem_type);
-
-			irValue *elem_size  = ir_const_int(esz);
-			irValue *elem_align = ir_const_int(eal);
-
-			irValue *len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
-
-			ir_emit_slice_bounds_check(proc, ast_token(ce->args[1]), v_zero, len, len, false);
-
-			irValue *slice_size = len;
-			if (esz != 1) {
-				slice_size = ir_emit_arith(proc, Token_Mul, elem_size, len, t_int);
-			}
-
-			TokenPos pos = ast_token(ce->args[0]).pos;
-
-			auto args = array_make<irValue *>(ir_allocator(), 3);
-			args[0] = slice_size;
-			args[1] = elem_align;
-			args[2] = ir_emit_source_code_location(proc, proc_name, pos);
-			irValue *call = ir_emit_package_call(proc, "mem", "alloc", args);
-
-			irValue *ptr = ir_emit_conv(proc, call, elem_ptr_type);
-			irValue *slice = ir_add_local_generated(proc, type);
-			ir_fill_slice(proc, slice, ptr, len);
-			return ir_emit_load(proc, slice);
-		} else if (is_type_map(type)) {
-			irValue *int_16 = ir_const_int(16);
-			irValue *cap = int_16;
-			if (ce->args.count == 2) {
-				cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
-			}
-
-			irValue *cond = ir_emit_comp(proc, Token_Gt, cap, v_zero);
-			cap = ir_emit_select(proc, cond, cap, int_16);
-
-			irValue *map = ir_add_local_generated(proc, type);
-			irValue *header = ir_gen_map_header(proc, map, base_type(type));
-
-			auto args = array_make<irValue *>(ir_allocator(), 3);
-			args[0] = header;
-			args[1] = cap;
-			args[2] = ir_emit_source_code_location(proc, ce->args[0]);
-			ir_emit_runtime_call(proc, "__dynamic_map_reserve", args);
-
-			return ir_emit_load(proc, map);
-		} else if (is_type_dynamic_array(type)) {
-			Type *elem_type = base_type(type)->DynamicArray.elem;
-			irValue *len = v_zero;
-			if (ce->args.count > 1) {
-				len = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
-			}
-			irValue *cap = len;
-			if (ce->args.count > 2) {
-				cap = ir_emit_conv(proc, ir_build_expr(proc, ce->args[2]), t_int);
-			}
-
-			ir_emit_dynamic_array_bounds_check(proc, ast_token(ce->args[0]), v_zero, len, cap);
-
-			irValue *array = ir_add_local_generated(proc, type);
-
-			auto args = array_make<irValue *>(ir_allocator(), 6);
-			args[0] = ir_emit_conv(proc, array, t_rawptr);
-			args[1] = ir_const_int(type_size_of(elem_type));
-			args[2] = ir_const_int(type_align_of(elem_type));
-			args[3] = len;
-			args[4] = cap;
-			args[5] = ir_emit_source_code_location(proc, ce->args[0]);
-			ir_emit_runtime_call(proc, "__dynamic_array_make", args);
-			return ir_emit_load(proc, array);
-		}
-		break;
-	}
-
-	#if 0
-	case BuiltinProc_free: {
-		ir_emit_comment(proc, str_lit("free"));
-
-		gbAllocator a = ir_allocator();
-
-		Ast *node = ce->args[0];
-		TypeAndValue tav = type_and_value_of_expr(node);
-		Type *type = base_type(tav.type);
-
-		if (is_type_dynamic_array(type)) {
-			irValue *val = ir_build_expr(proc, node);
-			irValue *da_allocator = ir_emit_struct_ev(proc, val, 3);
-
-			irValue *ptr = ir_emit_struct_ev(proc, val, 0);
-			ptr = ir_emit_conv(proc, ptr, t_rawptr);
-
-			irValue **args = gb_alloc_array(a, irValue *, 1);
-			args[0] = da_allocator;
-			args[1] = ptr;
-			return ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
-		} else if (is_type_map(type)) {
-			irValue *map = ir_build_expr(proc, node);
-			irValue *map_ptr = ir_address_from_load_or_generate_local(proc, map);
-
-			{
-				irValue *array = ir_emit_struct_ep(proc, map_ptr, 0);
-
-				irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
-				irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
-				da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
-
-				irValue **args = gb_alloc_array(a, irValue *, 1);
-				args[0] = da_allocator;
-				args[1] = da_ptr;
-				ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
-			}
-			{
-				irValue *array = ir_emit_struct_ep(proc, map_ptr, 1);
-
-				irValue *da_allocator = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 3));
-				irValue *da_ptr = ir_emit_load(proc, ir_emit_struct_ep(proc, array, 0));
-				da_ptr = ir_emit_conv(proc, da_ptr, t_rawptr);
-
-				irValue **args = gb_alloc_array(a, irValue *, 1);
-				args[0] = da_allocator;
-				args[1] = da_ptr;
-				ir_emit_runtime_call(proc, "free_ptr_with_allocator", args, 2);
-			}
-			return nullptr;
-		}
-
-		irValue *val = ir_build_expr(proc, node);
-		irValue *ptr = nullptr;
-		if (is_type_pointer(type)) {
-			ptr = val;
-		} else if (is_type_slice(type)) {
-			ptr = ir_slice_elem(proc, val);
-		} else if (is_type_string(type)) {
-			ptr = ir_string_elem(proc, val);
-		} else {
-			GB_PANIC("Invalid type to 'free'");
-		}
-
-		if (ptr == nullptr) {
-			return nullptr;
-		}
-
-		ptr = ir_emit_conv(proc, ptr, t_rawptr);
-
-		irValue **args = gb_alloc_array(a, irValue *, 1);
-		args[0] = ptr;
-		return ir_emit_runtime_call(proc, "free_ptr", args, 1);
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_reserve: {
-		ir_emit_comment(proc, str_lit("reserve"));
-		gbAllocator a = ir_allocator();
-
-		irValue *ptr = ir_build_addr_ptr(proc, ce->args[0]);
-		Type *type = ir_type(ptr);
-		GB_ASSERT(is_type_pointer(type));
-		type = base_type(type_deref(type));
-
-		irValue *capacity = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t_int);
-
-		if (is_type_dynamic_array(type)) {
-			Type *elem = type->DynamicArray.elem;
-
-			irValue *elem_size  = ir_const_int(type_size_of(elem));
-			irValue *elem_align = ir_const_int(type_align_of(elem));
-
-			ptr = ir_emit_conv(proc, ptr, t_rawptr);
-
-			irValue **args = gb_alloc_array(a, irValue *, 4);
-			args[0] = ptr;
-			args[1] = elem_size;
-			args[2] = elem_align;
-			args[3] = capacity;
-			return ir_emit_runtime_call(proc, "__dynamic_array_reserve", args, 4);
-		} else if (is_type_map(type)) {
-			irValue **args = gb_alloc_array(a, irValue *, 2);
-			args[0] = ir_gen_map_header(proc, ptr, type);
-			args[1] = capacity;
-			return ir_emit_runtime_call(proc, "__dynamic_map_reserve", args, 2);
-		} else {
-			GB_PANIC("Unknown type for 'reserve'");
-		}
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_clear: {
-		ir_emit_comment(proc, str_lit("clear"));
-		Type *original_type = type_of_expr(ce->args[0]);
-		irAddr const &addr = ir_build_addr(proc, ce->args[0]);
-		irValue *ptr = addr.addr;
-		if (is_double_pointer(ir_type(ptr))) {
-			ptr = ir_addr_load(proc, addr);
-		}
-		Type *t = base_type(type_deref(original_type));
-		if (is_type_dynamic_array(t)) {
-			irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
-			ir_emit_store(proc, count_ptr, v_zero);
-		} else if (is_type_map(t)) {
-			irValue *ha = ir_emit_struct_ep(proc, ptr, 0);
-			irValue *ea = ir_emit_struct_ep(proc, ptr, 1);
-			ir_emit_store(proc, ir_emit_struct_ep(proc, ha, 1), v_zero);
-			ir_emit_store(proc, ir_emit_struct_ep(proc, ea, 1), v_zero);
-		} else if (is_type_slice(t)) {
-			irValue *count_ptr = ir_emit_struct_ep(proc, ptr, 1);
-			ir_emit_store(proc, count_ptr, v_zero);
-		} else {
-			GB_PANIC("TODO(bill): ir clear for '%s'", type_to_string(t));
-		}
-		return nullptr;
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_append: {
-		ir_emit_comment(proc, str_lit("append"));
-		gbAllocator a = ir_allocator();
-
-		Type *value_type = type_of_expr(ce->args[0]);
-		irAddr array_addr = ir_build_addr(proc, ce->args[0]);
-		irValue *array_ptr = array_addr.addr;
-		if (is_double_pointer(ir_type(array_ptr))) {
-			array_ptr = ir_addr_load(proc, array_addr);
-		}
-		Type *type = ir_type(array_ptr);
-		{
-			TokenPos pos = ast_token(ce->args[0]).pos;
-			GB_ASSERT_MSG(is_type_pointer(type), "%.*s(%td) %s",
-			              LIT(pos.file), pos.line,
-			              type_to_string(type));
-		}
-		type = base_type(type_deref(type));
-		Type *elem_type = nullptr;
-		bool is_slice = false;
-		if (is_type_dynamic_array(type)) {
-			elem_type = type->DynamicArray.elem;
-		} else if (is_type_slice(type)) {
-			is_slice = true;
-			elem_type = type->Slice.elem;
-		} else {
-			GB_PANIC("Invalid type to append");
-		}
-
-		irValue *elem_size  = ir_const_int(type_size_of(elem_type));
-		irValue *elem_align = ir_const_int(type_align_of(elem_type));
-
-		array_ptr = ir_emit_conv(proc, array_ptr, t_rawptr);
-
-		isize arg_index = 0;
-		isize arg_count = 0;
-		for_array(i, ce->args) {
-			Ast *a = ce->args[i];
-			Type *at = base_type(type_of_expr(a));
-			if (at->kind == Type_Tuple) {
-				arg_count += at->Tuple.variable_count;
-			} else {
-				arg_count++;
-			}
-		}
-
-		irValue **args = gb_alloc_array(ir_allocator(), irValue *, arg_count);
-		bool vari_expand = ce->ellipsis.pos.line != 0;
-
-		for_array(i, ce->args) {
-			irValue *a = ir_build_expr(proc, ce->args[i]);
-			Type *at = ir_type(a);
-			if (at->kind == Type_Tuple) {
-				for (isize i = 0; i < at->Tuple.variable_count; i++) {
-					Entity *e = at->Tuple.variables[i];
-					irValue *v = ir_emit_struct_ev(proc, a, i);
-					args[arg_index++] = v;
-				}
-			} else {
-				args[arg_index++] = a;
-			}
-		}
-
-		if (!vari_expand) {
-			for (isize i = 1; i < arg_count; i++) {
-				args[i] = ir_emit_conv(proc, args[i], elem_type);
-			}
-		}
-
-		if (!vari_expand) {
-			ir_emit_comment(proc, str_lit("variadic call argument generation"));
-			Type *slice_type = alloc_type_slice(elem_type);
-			irValue *slice = ir_add_local_generated(proc, slice_type);
-			isize slice_len = arg_count-1;
-
-			if (slice_len > 0) {
-				irValue *base_array = ir_add_local_generated(proc, alloc_type_array(elem_type, slice_len));
-
-				for (isize i = 1; i < arg_count; i++) {
-					irValue *addr = ir_emit_array_epi(proc, base_array, i-1);
-					ir_emit_store(proc, addr, args[i]);
-				}
-
-				irValue *base_elem  = ir_emit_array_epi(proc, base_array, 0);
-				irValue *len = ir_const_int(slice_len);
-				ir_fill_slice(proc, slice, base_elem, len, len);
-			}
-
-			arg_count = 2;
-			args[arg_count-1] = ir_emit_load(proc, slice);
-		}
-
-		irValue *item_slice = args[1];
-		irValue *items = ir_slice_elem(proc, item_slice);
-		irValue *item_count = ir_slice_len(proc, item_slice);
-
-		irValue **daa_args = gb_alloc_array(a, irValue *, 5);
-		daa_args[0] = array_ptr;
-		daa_args[1] = elem_size;
-		daa_args[2] = elem_align;
-		daa_args[3] = ir_emit_conv(proc, items, t_rawptr);
-		daa_args[4] = ir_emit_conv(proc, item_count, t_int);
-
-		if (is_slice) {
-		return ir_emit_runtime_call(proc, "__slice_append", daa_args, 5);
-		}
-		return ir_emit_runtime_call(proc, "__dynamic_array_append", daa_args, 5);
-		break;
-	}
-	#endif
-	#if 0
-	case BuiltinProc_delete: {
-		ir_emit_comment(proc, str_lit("delete"));
-		irValue *map = ir_build_expr(proc, ce->args[0]);
-		irValue *key = ir_build_expr(proc, ce->args[1]);
-		Type *map_type = ir_type(map);
-		GB_ASSERT(is_type_map(map_type));
-		Type *key_type = base_type(map_type)->Map.key;
-
-		irValue *addr = ir_address_from_load_or_generate_local(proc, map);
-
-		gbAllocator a = ir_allocator();
-		irValue **args = gb_alloc_array(a, irValue *, 2);
-		args[0] = ir_gen_map_header(proc, addr, map_type);
-		args[1] = ir_gen_map_key(proc, key, key_type);
-		return ir_emit_runtime_call(proc, "__dynamic_map_delete", args, 2);
-		break;
-	}
-	#endif
-
 	case BuiltinProc_swizzle: {
 		ir_emit_comment(proc, str_lit("swizzle.begin"));
 		irAddr const &addr = ir_build_addr(proc, ce->args[0]);