Browse Source

Begin working on a minimum build

gingerBill 2 years ago
parent
commit
99c812b02d
10 changed files with 1304 additions and 254 deletions
  1. 3 0
      src/checker.cpp
  2. 43 1
      src/tilde.cpp
  3. 7 2
      src/tilde.hpp
  4. BIN
      src/tilde/tb.lib
  5. 133 0
      src/tilde_builtin.cpp
  6. 78 31
      src/tilde_const.cpp
  7. 5 1
      src/tilde_debug.cpp
  8. 750 129
      src/tilde_expr.cpp
  9. 67 35
      src/tilde_proc.cpp
  10. 218 55
      src/tilde_stmt.cpp

+ 3 - 0
src/checker.cpp

@@ -1046,6 +1046,7 @@ gb_internal void init_universal(void) {
 	add_global_bool_constant("ODIN_NO_RTTI",            bc->no_rtti);
 	add_global_bool_constant("ODIN_NO_RTTI",            bc->no_rtti);
 
 
 	add_global_bool_constant("ODIN_VALGRIND_SUPPORT",         bc->ODIN_VALGRIND_SUPPORT);
 	add_global_bool_constant("ODIN_VALGRIND_SUPPORT",         bc->ODIN_VALGRIND_SUPPORT);
+	add_global_bool_constant("ODIN_TILDE",                    bc->tilde_backend);
 
 
 	add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
 	add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
 
 
@@ -2311,7 +2312,9 @@ gb_internal void generate_minimum_dependency_set(Checker *c, Entity *start) {
 		str_lit("memory_equal"),
 		str_lit("memory_equal"),
 		str_lit("memory_compare"),
 		str_lit("memory_compare"),
 		str_lit("memory_compare_zero"),
 		str_lit("memory_compare_zero"),
+	);
 
 
+	FORCE_ADD_RUNTIME_ENTITIES(!build_context.tilde_backend,
 		// Extended data type internal procedures
 		// Extended data type internal procedures
 		str_lit("umodti3"),
 		str_lit("umodti3"),
 		str_lit("udivti3"),
 		str_lit("udivti3"),

+ 43 - 1
src/tilde.cpp

@@ -126,6 +126,19 @@ gb_internal cgValue cg_lvalue_addr(TB_Node *node, Type *type) {
 	return v;
 	return v;
 }
 }
 
 
+gb_internal cgValue cg_lvalue_addr_to_value(cgValue v) {
+	if (v.kind == cgValue_Value) {
+		GB_ASSERT(is_type_pointer(v.type));
+		GB_ASSERT(v.node->dt.type == TB_PTR);
+	} else {
+		GB_ASSERT(v.kind == cgValue_Addr);
+		GB_ASSERT(v.node->dt.type == TB_PTR);
+		v.kind = cgValue_Value;
+		v.type = alloc_type_pointer(v.type);
+	}
+	return v;
+}
+
 gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) {
 gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) {
 	GB_ASSERT(type->kind == Type_Tuple);
 	GB_ASSERT(type->kind == Type_Tuple);
 	GB_ASSERT(multi != nullptr);
 	GB_ASSERT(multi != nullptr);
@@ -138,6 +151,24 @@ gb_internal cgValue cg_value_multi(cgValueMulti *multi, Type *type) {
 	return v;
 	return v;
 }
 }
 
 
+gb_internal cgValue cg_value_multi(Slice<cgValue> const &values, Type *type) {
+	cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti);
+	multi->values = values;
+	return cg_value_multi(multi, type);
+}
+
+
+gb_internal cgValue cg_value_multi2(cgValue const &x, cgValue const &y, Type *type) {
+	GB_ASSERT(type->kind == Type_Tuple);
+	GB_ASSERT(type->Tuple.variables.count == 2);
+	cgValueMulti *multi = gb_alloc_item(permanent_allocator(), cgValueMulti);
+	multi->values = slice_make<cgValue>(permanent_allocator(), 2);
+	multi->values[0] = x;
+	multi->values[1] = y;
+	return cg_value_multi(multi, type);
+}
+
+
 gb_internal cgAddr cg_addr(cgValue const &value) {
 gb_internal cgAddr cg_addr(cgValue const &value) {
 	GB_ASSERT(value.kind != cgValue_Multi);
 	GB_ASSERT(value.kind != cgValue_Multi);
 	cgAddr addr = {};
 	cgAddr addr = {};
@@ -151,10 +182,21 @@ gb_internal cgAddr cg_addr(cgValue const &value) {
 	return addr;
 	return addr;
 }
 }
 
 
+gb_internal void cg_set_debug_pos_from_node(cgProcedure *p, Ast *node) {
+	if (node) {
+		TokenPos pos = ast_token(node).pos;
+		TB_FileID *file_id = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id);
+		if (file_id) {
+			tb_inst_set_location(p->func, *file_id, pos.line);
+		}
+	}
+}
+
 
 
 gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) {
 gb_internal void cg_add_entity(cgModule *m, Entity *e, cgValue const &val) {
 	if (e) {
 	if (e) {
 		rw_mutex_lock(&m->values_mutex);
 		rw_mutex_lock(&m->values_mutex);
+		GB_ASSERT(val.node != nullptr);
 		map_set(&m->values, e, val);
 		map_set(&m->values, e, val);
 		rw_mutex_unlock(&m->values_mutex);
 		rw_mutex_unlock(&m->values_mutex);
 	}
 	}
@@ -744,7 +786,7 @@ gb_internal bool cg_generate_code(Checker *c) {
 	}
 	}
 
 
 	TB_DebugFormat debug_format = TB_DEBUGFMT_NONE;
 	TB_DebugFormat debug_format = TB_DEBUGFMT_NONE;
-	if (build_context.ODIN_DEBUG) {
+	if (build_context.ODIN_DEBUG || true) {
 		switch (build_context.metrics.os) {
 		switch (build_context.metrics.os) {
 		case TargetOs_windows:
 		case TargetOs_windows:
 			debug_format = TB_DEBUGFMT_CODEVIEW;
 			debug_format = TB_DEBUGFMT_CODEVIEW;

+ 7 - 2
src/tilde.hpp

@@ -272,6 +272,7 @@ gb_internal void cg_build_when_stmt(cgProcedure *p, AstWhenStmt *ws);
 gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr);
 gb_internal cgValue cg_build_expr(cgProcedure *p, Ast *expr);
 gb_internal cgAddr  cg_build_addr(cgProcedure *p, Ast *expr);
 gb_internal cgAddr  cg_build_addr(cgProcedure *p, Ast *expr);
 gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr);
 gb_internal cgValue cg_build_addr_ptr(cgProcedure *p, Ast *expr);
+gb_internal cgValue cg_build_cond(cgProcedure *p, Ast *cond, TB_Node *true_block, TB_Node *false_block);
 
 
 gb_internal Type *  cg_addr_type(cgAddr const &addr);
 gb_internal Type *  cg_addr_type(cgAddr const &addr);
 gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr);
 gb_internal cgValue cg_addr_load(cgProcedure *p, cgAddr addr);
@@ -279,13 +280,15 @@ gb_internal void    cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value);
 gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr);
 gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr);
 
 
 gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false);
 gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false);
-gb_internal void    cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile=false);
+gb_internal void    cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile=false);
 
 
 gb_internal cgAddr  cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init);
 gb_internal cgAddr  cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init);
 gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value);
 gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value);
 gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment);
 gb_internal cgValue cg_copy_value_to_ptr(cgProcedure *p, cgValue value, Type *original_type, isize min_alignment);
 
 
 gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr);
 gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr);
+gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return_results);
+gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice<cgValue> const &results);
 
 
 gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e);
 gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e);
 
 
@@ -300,6 +303,7 @@ gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index);
 gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index);
 gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index);
 gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index);
 gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index);
 gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel);
 gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel);
+gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index);
 
 
 gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t);
 gb_internal cgValue cg_emit_conv(cgProcedure *p, cgValue value, Type *t);
 gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind, cgValue x);
 gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind, cgValue x);
@@ -315,4 +319,5 @@ gb_internal isize cg_append_tuple_values(cgProcedure *p, Array<cgValue> *dst_val
 gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos);
 gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type, ParameterValue const &param_value, TokenPos const &pos);
 
 
 gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
 gb_internal cgValue cg_builtin_len(cgProcedure *p, cgValue value);
-gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
+gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &x);
+

BIN
src/tilde/tb.lib


+ 133 - 0
src/tilde_builtin.cpp

@@ -61,6 +61,7 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
 			cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
 			cgValue ptr = cg_value(value.node, alloc_type_pointer(value.type));
 			cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0);
 			cgValue data_ptr = cg_emit_struct_ep(p, ptr, 0);
 			res = cg_emit_load(p, data_ptr);
 			res = cg_emit_load(p, data_ptr);
+			GB_ASSERT(is_type_multi_pointer(res.type));
 		}
 		}
 		break;
 		break;
 	case Type_DynamicArray:
 	case Type_DynamicArray:
@@ -82,7 +83,12 @@ gb_internal cgValue cg_builtin_raw_data(cgProcedure *p, cgValue const &value) {
 		}
 		}
 		break;
 		break;
 	case Type_Pointer:
 	case Type_Pointer:
+		GB_ASSERT(is_type_array_like(t->Pointer.elem));
+		GB_ASSERT(value.kind == cgValue_Value);
+		res = cg_value(value.node, alloc_type_multi_pointer(base_array_type(t->Pointer.elem)));
+		break;
 	case Type_MultiPointer:
 	case Type_MultiPointer:
+
 		GB_PANIC("TODO(bill) %s", type_to_string(value.type));
 		GB_PANIC("TODO(bill) %s", type_to_string(value.type));
 		// res = cg_emit_conv(p, value, tv.type);
 		// res = cg_emit_conv(p, value, tv.type);
 		break;
 		break;
@@ -102,6 +108,37 @@ gb_internal cgValue cg_builtin_max(cgProcedure *p, Type *t, cgValue x, cgValue y
 	return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y);
 	return cg_emit_select(p, cg_emit_comp(p, Token_Gt, x, y), x, y);
 }
 }
 
 
+gb_internal cgValue cg_builtin_abs(cgProcedure *p, cgValue x) {
+	if (is_type_unsigned(x.type)) {
+		return x;
+	}
+
+	if (is_type_quaternion(x.type)) {
+		GB_PANIC("TODO(bill): abs quaternion");
+	} else if (is_type_complex(x.type)) {
+		GB_PANIC("TODO(bill): abs complex");
+	}
+
+	TB_DataType dt = cg_data_type(x.type);
+	GB_ASSERT(!TB_IS_VOID_TYPE(dt));
+	TB_Node *zero = nullptr;
+	if (dt.type == TB_FLOAT) {
+		if (dt.data == 32) {
+			zero = tb_inst_float32(p->func, 0);
+		} else if (dt.data == 64) {
+			zero = tb_inst_float64(p->func, 0);
+		}
+	} else {
+		zero = tb_inst_uint(p->func, dt, 0);
+	}
+	GB_ASSERT(zero != nullptr);
+
+	cgValue cond = cg_emit_comp(p, Token_Lt, x, cg_value(zero, x.type));
+	cgValue neg = cg_emit_unary_arith(p, Token_Sub, x, x.type);
+	return cg_emit_select(p, cond, neg, x);
+}
+
+
 
 
 gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
 gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr) {
 	ast_node(ce, CallExpr, expr);
 	ast_node(ce, CallExpr, expr);
@@ -149,6 +186,12 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 		return cg_builtin_len(p, v);
 		return cg_builtin_len(p, v);
 	}
 	}
 
 
+	case BuiltinProc_raw_data:
+		{
+			cgValue v = cg_build_expr(p, ce->args[0]);
+			return cg_builtin_raw_data(p, v);
+		}
+
 	case BuiltinProc_min:
 	case BuiltinProc_min:
 		if (ce->args.count == 2) {
 		if (ce->args.count == 2) {
 			Type *t = type_of_expr(expr);
 			Type *t = type_of_expr(expr);
@@ -176,6 +219,96 @@ gb_internal cgValue cg_build_builtin(cgProcedure *p, BuiltinProcId id, Ast *expr
 		}
 		}
 		break;
 		break;
 
 
+	case BuiltinProc_abs:
+		{
+			cgValue x = cg_build_expr(p, ce->args[0]);
+			return cg_builtin_abs(p, x);
+		}
+
+	case BuiltinProc_debug_trap:
+		tb_inst_debugbreak(p->func);
+		return {};
+	case BuiltinProc_trap:
+		tb_inst_trap(p->func);
+		return {};
+
+	case BuiltinProc_mem_zero:
+		{
+			cgValue ptr = cg_build_expr(p, ce->args[0]);
+			cgValue len = cg_build_expr(p, ce->args[1]);
+			GB_ASSERT(ptr.kind == cgValue_Value);
+			GB_ASSERT(len.kind == cgValue_Value);
+			tb_inst_memzero(p->func, ptr.node, len.node, 1, false);
+			return {};
+		}
+
+	case BuiltinProc_mem_copy:
+		{
+			cgValue dst = cg_build_expr(p, ce->args[0]);
+			cgValue src = cg_build_expr(p, ce->args[1]);
+			cgValue len = cg_build_expr(p, ce->args[2]);
+			GB_ASSERT(dst.kind == cgValue_Value);
+			GB_ASSERT(src.kind == cgValue_Value);
+			GB_ASSERT(len.kind == cgValue_Value);
+			// TODO(bill): This needs to be memmove
+			tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
+			return {};
+		}
+
+	case BuiltinProc_mem_copy_non_overlapping:
+		{
+			cgValue dst = cg_build_expr(p, ce->args[0]);
+			cgValue src = cg_build_expr(p, ce->args[1]);
+			cgValue len = cg_build_expr(p, ce->args[2]);
+			GB_ASSERT(dst.kind == cgValue_Value);
+			GB_ASSERT(src.kind == cgValue_Value);
+			GB_ASSERT(len.kind == cgValue_Value);
+			tb_inst_memcpy(p->func, dst.node, src.node, len.node, 1, false);
+			return {};
+		}
+
+
+	case BuiltinProc_overflow_add:
+		{
+			Type *res_type = type_of_expr(expr);
+			GB_ASSERT(res_type->kind == Type_Tuple);
+			GB_ASSERT(res_type->Tuple.variables.count == 2);
+			// TODO(bill): do a proper overflow add
+			Type *type = res_type->Tuple.variables[0]->type;
+			Type *ok_type = res_type->Tuple.variables[1]->type;
+			cgValue x = cg_build_expr(p, ce->args[0]);
+			cgValue y = cg_build_expr(p, ce->args[1]);
+			x = cg_emit_conv(p, x, type);
+			y = cg_emit_conv(p, y, type);
+			cgValue res = cg_emit_arith(p, Token_Add, x, y, type);
+			cgValue ok  = cg_const_int(p, ok_type, false);
+
+			return cg_value_multi2(res, ok, res_type);
+		}
+
+
+	case BuiltinProc_ptr_offset:
+		{
+			cgValue ptr = cg_build_expr(p, ce->args[0]);
+			cgValue len = cg_build_expr(p, ce->args[1]);
+			len = cg_emit_conv(p, len, t_int);
+			return cg_emit_ptr_offset(p, ptr, len);
+		}
+	case BuiltinProc_ptr_sub:
+		{
+			Type *elem0 = type_deref(type_of_expr(ce->args[0]));
+			Type *elem1 = type_deref(type_of_expr(ce->args[1]));
+			GB_ASSERT(are_types_identical(elem0, elem1));
+			Type *elem = elem0;
+
+			cgValue ptr0 = cg_emit_conv(p, cg_build_expr(p, ce->args[0]), t_uintptr);
+			cgValue ptr1 = cg_emit_conv(p, cg_build_expr(p, ce->args[1]), t_uintptr);
+
+			cgValue diff = cg_emit_arith(p, Token_Sub, ptr0, ptr1, t_uintptr);
+			diff = cg_emit_conv(p, diff, t_int);
+			return cg_emit_arith(p, Token_Quo, diff, cg_const_int(p, t_int, type_size_of(elem)), t_int);
+		}
+
 	}
 	}
 
 
 
 

+ 78 - 31
src/tilde_const.cpp

@@ -52,6 +52,13 @@ gb_internal cgValue cg_const_nil(cgProcedure *p, Type *type) {
 }
 }
 
 
 
 
+gb_internal cgValue cg_emit_source_code_location_as_global(cgProcedure *p, String const &proc_name, TokenPos pos) {
+	// TODO(bill): cg_emit_source_code_location_as_global
+	return cg_const_nil(p, t_source_code_location);
+}
+
+
+
 gb_internal void cg_write_big_int_at_ptr(void *dst, BigInt const *a, Type *original_type) {
 gb_internal void cg_write_big_int_at_ptr(void *dst, BigInt const *a, Type *original_type) {
 	GB_ASSERT(build_context.endian_kind == TargetEndian_Little);
 	GB_ASSERT(build_context.endian_kind == TargetEndian_Little);
 	size_t sz = cast(size_t)type_size_of(original_type);
 	size_t sz = cast(size_t)type_size_of(original_type);
@@ -109,7 +116,6 @@ gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Ty
 
 
 	char name[32] = {};
 	char name[32] = {};
 	gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1));
 	gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1));
-
 	TB_Global *str_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
 	TB_Global *str_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
 	i64 size = str.len+1;
 	i64 size = str.len+1;
 	tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, size, 1, 1);
 	tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, size, 1, 1);
@@ -125,6 +131,7 @@ gb_internal TB_Global *cg_global_const_string(cgModule *m, String const &str, Ty
 	}
 	}
 
 
 	if (global == nullptr) {
 	if (global == nullptr) {
+		gb_snprintf(name, 31, "cstr$%u", 1+m->const_nil_guid.fetch_add(1));
 		global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE);
 		global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE);
 		tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(type), type_align_of(type), 2);
 		tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), global, type_size_of(type), type_align_of(type), 2);
 	}
 	}
@@ -778,18 +785,47 @@ gb_internal TB_Global *cg_global_const_comp_literal(cgModule *m, Type *original_
 }
 }
 
 
 
 
-gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, ExactValue const &value) {
+gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) {
+	GB_ASSERT(p != nullptr);
 	TB_Node *node = nullptr;
 	TB_Node *node = nullptr;
 
 
+	if (is_type_untyped(type)) {
+		// TODO(bill): THIS IS A COMPLETE HACK, WHY DOES THIS NOT A TYPE?
+		GB_ASSERT(type->kind == Type_Basic);
+		switch (type->Basic.kind) {
+		case Basic_UntypedBool:
+			type = t_bool;
+			break;
+		case Basic_UntypedInteger:
+			type = t_i64;
+			break;
+		case Basic_UntypedFloat:
+			type = t_f64;
+			break;
+		case Basic_UntypedComplex:
+			type = t_complex128;
+			break;
+		case Basic_UntypedQuaternion:
+			type = t_quaternion256;
+			break;
+		case Basic_UntypedString:
+			type = t_string;
+			break;
+		case Basic_UntypedRune:
+			type = t_rune;
+			break;
+		case Basic_UntypedNil:
+		case Basic_UntypedUninit:
+			return cg_value(cast(TB_Node *)nullptr, type);
+		}
+	}
 	TB_DataType dt = cg_data_type(type);
 	TB_DataType dt = cg_data_type(type);
 
 
 	switch (value.kind) {
 	switch (value.kind) {
 	case ExactValue_Invalid:
 	case ExactValue_Invalid:
-		GB_ASSERT(p != nullptr);
 		return cg_const_nil(p, type);
 		return cg_const_nil(p, type);
 
 
 	case ExactValue_Typeid:
 	case ExactValue_Typeid:
-		GB_ASSERT(p != nullptr);
 		return cg_typeid(p, value.value_typeid);
 		return cg_typeid(p, value.value_typeid);
 
 
 	case ExactValue_Procedure:
 	case ExactValue_Procedure:
@@ -797,13 +833,13 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 			Ast *expr = unparen_expr(value.value_procedure);
 			Ast *expr = unparen_expr(value.value_procedure);
 			Entity *e = entity_of_node(expr);
 			Entity *e = entity_of_node(expr);
 			if (e != nullptr) {
 			if (e != nullptr) {
-				cgValue found = cg_find_procedure_value_from_entity(m, e);
-				GB_ASSERT(are_types_identical(type, found.type));
+				cgValue found = cg_find_procedure_value_from_entity(p->module, e);
+				GB_ASSERT_MSG(are_types_identical(type, found.type),
+				              "%.*s %s == %s",
+				              LIT(p->name),
+				              type_to_string(type), type_to_string(found.type));
 				GB_ASSERT(found.kind == cgValue_Symbol);
 				GB_ASSERT(found.kind == cgValue_Symbol);
-				if (p) {
-					return cg_flatten_value(p, found);
-				}
-				return found;
+				return cg_flatten_value(p, found);
 			}
 			}
 			GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure");
 			GB_PANIC("TODO(bill): cg_const_value ExactValue_Procedure");
 		}
 		}
@@ -812,12 +848,10 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 
 
 	switch (value.kind) {
 	switch (value.kind) {
 	case ExactValue_Bool:
 	case ExactValue_Bool:
-		GB_ASSERT(p != nullptr);
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type);
 		return cg_value(tb_inst_uint(p->func, dt, value.value_bool), type);
 
 
 	case ExactValue_Integer:
 	case ExactValue_Integer:
-		GB_ASSERT(p != nullptr);
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		// GB_ASSERT(dt.raw != TB_TYPE_I128.raw);
 		// GB_ASSERT(dt.raw != TB_TYPE_I128.raw);
 		if (is_type_unsigned(type)) {
 		if (is_type_unsigned(type)) {
@@ -830,7 +864,6 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 		break;
 		break;
 
 
 	case ExactValue_Float:
 	case ExactValue_Float:
-		GB_ASSERT(p != nullptr);
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		GB_ASSERT(!TB_IS_VOID_TYPE(dt));
 		GB_ASSERT(dt.raw != TB_TYPE_F16.raw);
 		GB_ASSERT(dt.raw != TB_TYPE_F16.raw);
 		GB_ASSERT(!is_type_different_to_arch_endianness(type));
 		GB_ASSERT(!is_type_different_to_arch_endianness(type));
@@ -846,13 +879,36 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 
 
 	case ExactValue_String:
 	case ExactValue_String:
 		{
 		{
-			TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_string(m, value.value_string, type, nullptr, 0);
-			if (p) {
-				TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
-				return cg_lvalue_addr(node, type);
-			} else {
-				return cg_value(symbol, alloc_type_pointer(type));
+			GB_ASSERT(is_type_string(type));
+			cgModule *m = p->module;
+
+			String str = value.value_string;
+
+			char name[32] = {};
+			gb_snprintf(name, 31, "csb$%u", 1+m->const_nil_guid.fetch_add(1));
+			TB_Global *cstr_global = tb_global_create(m->mod, -1, name, nullptr, TB_LINKAGE_PRIVATE);
+			i64 size = str.len+1;
+			tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), cstr_global, size, 1, 1);
+			u8 *data = cast(u8 *)tb_global_add_region(m->mod, cstr_global, 0, size);
+			gb_memcopy(data, str.text, str.len);
+			data[str.len] = 0;
+
+			if (is_type_cstring(type)) {
+				cgValue s = cg_value(cstr_global, type);
+				return cg_flatten_value(p, s);
 			}
 			}
+
+			gb_snprintf(name, 31, "str$%u", 1+m->const_nil_guid.fetch_add(1));
+			TB_Global *str_global = tb_global_create(m->mod, -1, name, cg_debug_type(m, type), TB_LINKAGE_PRIVATE);
+			tb_global_set_storage(m->mod, tb_module_get_rdata(m->mod), str_global, type_size_of(type), type_align_of(type), 2);
+
+			tb_global_add_symbol_reloc(m->mod, str_global, 0, cast(TB_Symbol *)cstr_global);
+			void *len_ptr = tb_global_add_region(m->mod, str_global, build_context.int_size, build_context.int_size);
+			cg_write_int_at_ptr(len_ptr, str.len, t_int);
+
+			TB_Node *s = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)str_global);
+			return cg_lvalue_addr(s, type);
+
 		}
 		}
 
 
 	case ExactValue_Pointer:
 	case ExactValue_Pointer:
@@ -860,13 +916,9 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 
 
 	case ExactValue_Compound:
 	case ExactValue_Compound:
 		{
 		{
-			TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_comp_literal(m, type, value, nullptr, 0);
-			if (p) {
-				TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
-				return cg_lvalue_addr(node, type);
-			} else {
-				return cg_value(symbol, type);
-			}
+			TB_Symbol *symbol = cast(TB_Symbol *)cg_global_const_comp_literal(p->module, type, value, nullptr, 0);
+			TB_Node *node = tb_inst_get_symbol_address(p->func, symbol);
+			return cg_lvalue_addr(node, type);
 		}
 		}
 		break;
 		break;
 	}
 	}
@@ -876,11 +928,6 @@ gb_internal cgValue cg_const_value(cgModule *m, cgProcedure *p, Type *type, Exac
 	return cg_value(node, type);
 	return cg_value(node, type);
 }
 }
 
 
-gb_internal cgValue cg_const_value(cgProcedure *p, Type *type, ExactValue const &value) {
-	GB_ASSERT(p != nullptr);
-	return cg_const_value(p->module, p, type, value);
-}
-
 gb_internal cgValue cg_const_int(cgProcedure *p, Type *type, i64 i) {
 gb_internal cgValue cg_const_int(cgProcedure *p, Type *type, i64 i) {
 	return cg_const_value(p, type, exact_value_i64(i));
 	return cg_const_value(p, type, exact_value_i64(i));
 }
 }

+ 5 - 1
src/tilde_debug.cpp

@@ -368,7 +368,11 @@ gb_internal TB_DebugType *cg_debug_type_internal(cgModule *m, Type *type) {
 				param_count += 1;
 				param_count += 1;
 			}
 			}
 
 
-			TB_DebugType *func = tb_debug_create_func(m->mod, TB_CDECL, param_count, return_count, pt->c_vararg);
+			TB_CallingConv tb_cc = TB_CDECL;
+			if (pt->calling_convention == ProcCC_StdCall) {
+				tb_cc = TB_STDCALL;
+			}
+			TB_DebugType *func = tb_debug_create_func(m->mod, tb_cc, param_count, return_count, pt->c_vararg);
 
 
 			map_set(&m->proc_debug_type_map, original_type, func);
 			map_set(&m->proc_debug_type_map, original_type, func);
 			map_set(&m->proc_debug_type_map, type, func);
 			map_set(&m->proc_debug_type_map, type, func);

File diff suppressed because it is too large
+ 750 - 129
src/tilde_expr.cpp


+ 67 - 35
src/tilde_proc.cpp

@@ -86,6 +86,10 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
 		}
 		}
 		p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL);
 		p->symbol = cast(TB_Symbol *)tb_extern_create(m->mod, link_name.len, cast(char const *)link_name.text, TB_EXTERNAL_SO_LOCAL);
 	}
 	}
+	if (p->name == "main") {
+		// TODO(bill): figure out when this should be public or not
+		linkage = TB_LINKAGE_PUBLIC;
+	}
 
 
 	if (p->symbol == nullptr)  {
 	if (p->symbol == nullptr)  {
 		p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
 		p->func = tb_function_create(m->mod, link_name.len, cast(char const *)link_name.text, linkage, TB_COMDAT_NONE);
@@ -97,9 +101,9 @@ gb_internal cgProcedure *cg_procedure_create(cgModule *m, Entity *entity, bool i
 		p->symbol = cast(TB_Symbol *)p->func;
 		p->symbol = cast(TB_Symbol *)p->func;
 	}
 	}
 
 
-	cgValue proc_value = cg_value(p->symbol, p->type);
-	cg_add_entity(m, entity, proc_value);
-	cg_add_member(m, p->name, proc_value);
+	p->value = cg_value(p->symbol, p->type);
+	cg_add_entity(m, entity, p->value);
+	cg_add_member(m, p->name, p->value);
 	cg_add_procedure_value(m, p);
 	cg_add_procedure_value(m, p);
 
 
 
 
@@ -275,7 +279,9 @@ gb_internal void cg_procedure_begin(cgProcedure *p) {
 		// }
 		// }
 	}
 	}
 
 
-	p->split_returns_index = param_index;
+	if (is_odin_like_cc) {
+		p->split_returns_index = param_index;
+	}
 
 
 	if (pt->calling_convention == ProcCC_Odin) {
 	if (pt->calling_convention == ProcCC_Odin) {
 		// NOTE(bill): Push context on to stack from implicit parameter
 		// NOTE(bill): Push context on to stack from implicit parameter
@@ -323,9 +329,15 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
 		return;
 		return;
 	}
 	}
 	if (tb_inst_get_control(p->func)) {
 	if (tb_inst_get_control(p->func)) {
+		GB_ASSERT(p->type->Proc.result_count == 0);
 		tb_inst_ret(p->func, 0, nullptr);
 		tb_inst_ret(p->func, 0, nullptr);
 	}
 	}
 	bool emit_asm = false;
 	bool emit_asm = false;
+
+	if (string_starts_with(p->name, str_lit("bug@main"))) {
+		// emit_asm = true;
+	}
+
 	TB_FunctionOutput *output = tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST, emit_asm);
 	TB_FunctionOutput *output = tb_module_compile_function(p->module->mod, p->func, TB_ISEL_FAST, emit_asm);
 	if (emit_asm) {
 	if (emit_asm) {
 		TB_Assembly *assembly = tb_output_get_asm(output);
 		TB_Assembly *assembly = tb_output_get_asm(output);
@@ -336,47 +348,70 @@ gb_internal void cg_procedure_end(cgProcedure *p) {
 	}
 	}
 }
 }
 
 
-gb_global String procedures_to_generate_list[] = {
-	str_lit("bug" ABI_PKG_NAME_SEPARATOR "main"),
-	str_lit("main"),
-};
-
 gb_internal void cg_procedure_generate(cgProcedure *p) {
 gb_internal void cg_procedure_generate(cgProcedure *p) {
 	if (p->body == nullptr) {
 	if (p->body == nullptr) {
 		return;
 		return;
 	}
 	}
 
 
-	bool build_body = false;
-
-	if (
-	    string_starts_with(p->name, str_lit("runtime" ABI_PKG_NAME_SEPARATOR "_os_write")) ||
-	    // p->name == "bug" ABI_PKG_NAME_SEPARATOR "main" ||
-	    // p->name == "main" ||
-	    false
-	) {
-		build_body = true;
-	}
-
-	if (build_body) {
-		cg_procedure_begin(p);
-		cg_build_stmt(p, p->body);
-	}
+	cg_procedure_begin(p);
+	cg_build_stmt(p, p->body);
 	cg_procedure_end(p);
 	cg_procedure_end(p);
 
 
-	if (build_body) {
+	if (string_starts_with(p->name, str_lit("bug@main"))) { // IR Printing
 		TB_Arena *arena = tb_default_arena();
 		TB_Arena *arena = tb_default_arena();
 		defer (arena->free(arena));
 		defer (arena->free(arena));
 		TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena);
 		TB_FuncOpt *opt = tb_funcopt_enter(p->func, arena);
 		defer (tb_funcopt_exit(opt));
 		defer (tb_funcopt_exit(opt));
 		tb_funcopt_print(opt);
 		tb_funcopt_print(opt);
+		fprintf(stdout, "\n");
+	}
+	if (false) { // GraphViz printing
+		tb_function_print(p->func, tb_default_print_callback, stdout);
+	}
+}
+
+gb_internal void cg_build_nested_proc(cgProcedure *p, AstProcLit *pd, Entity *e) {
+	GB_ASSERT(pd->body != nullptr);
+	cgModule *m = p->module;
+	auto *min_dep_set = &m->info->minimum_dependency_set;
+
+	if (ptr_set_exists(min_dep_set, e) == false) {
+		// NOTE(bill): Nothing depends upon it so doesn't need to be built
+		return;
+	}
 
 
-		// GraphViz printing
-		// tb_function_print(p->func, tb_default_print_callback, stdout);
+	// NOTE(bill): Generate a new name
+	// parent.name-guid
+	String original_name = e->token.string;
+	String pd_name = original_name;
+	if (e->Procedure.link_name.len > 0) {
+		pd_name = e->Procedure.link_name;
 	}
 	}
+
+
+	isize name_len = p->name.len + 1 + pd_name.len + 1 + 10 + 1;
+	char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
+
+	i32 guid = cast(i32)p->children.count;
+	name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%d", LIT(p->name), LIT(pd_name), guid);
+	String name = make_string(cast(u8 *)name_text, name_len-1);
+
+	e->Procedure.link_name = name;
+
+	cgProcedure *nested_proc = cg_procedure_create(p->module, e);
+	e->cg_procedure = nested_proc;
+
+	cgValue value = nested_proc->value;
+
+	cg_add_entity(m, e, value);
+	array_add(&p->children, nested_proc);
+	array_add(&m->procedures_to_generate, nested_proc);
 }
 }
 
 
 
 
 
 
+
+
 gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) {
 gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e) {
 	GB_ASSERT(is_type_proc(e->type));
 	GB_ASSERT(is_type_proc(e->type));
 	e = strip_entity_wrapping(e);
 	e = strip_entity_wrapping(e);
@@ -388,6 +423,7 @@ gb_internal cgValue cg_find_procedure_value_from_entity(cgModule *m, Entity *e)
 	found = map_get(&m->values, e);
 	found = map_get(&m->values, e);
 	rw_mutex_shared_unlock(&m->values_mutex);
 	rw_mutex_shared_unlock(&m->values_mutex);
 	if (found) {
 	if (found) {
+		GB_ASSERT(found->node != nullptr);
 		return *found;
 		return *found;
 	}
 	}
 
 
@@ -408,9 +444,6 @@ gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr) {
 		GB_ASSERT(res.kind == cgValue_Multi);
 		GB_ASSERT(res.kind == cgValue_Multi);
 		GB_ASSERT(res.multi->values.count == 2);
 		GB_ASSERT(res.multi->values.count == 2);
 		return res.multi->values[0];
 		return res.multi->values[0];
-		// GB_ASSERT(is_type_tuple(res.type));
-		// GB_ASSERT(res.type->Tuple.variables.count == 2);
-		// return cg_emit_struct_ev(p, res, 0);
 	}
 	}
 	return res;
 	return res;
 }
 }
@@ -470,8 +503,9 @@ gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice<cgValue>
 			params[param_index++] = local;
 			params[param_index++] = local;
 		}
 		}
 	}
 	}
-	for (cgValue arg : args) {
-		Type *param_type = param_entities[param_index]->type;
+	for_array(i, args) {
+		Type *param_type = param_entities[i]->type;
+		cgValue arg = args[i];
 		arg = cg_emit_conv(p, arg, param_type);
 		arg = cg_emit_conv(p, arg, param_type);
 		arg = cg_flatten_value(p, arg);
 		arg = cg_flatten_value(p, arg);
 
 
@@ -629,9 +663,7 @@ gb_internal cgValue cg_handle_param_value(cgProcedure *p, Type *parameter_type,
 			if (p->entity != nullptr) {
 			if (p->entity != nullptr) {
 				proc_name = p->entity->token.string;
 				proc_name = p->entity->token.string;
 			}
 			}
-			GB_PANIC("TODO(bill): cg_emit_source_code_location_as_global");
-			// return cg_emit_source_code_location_as_global(p, proc_name, pos);
-			break;
+			return cg_emit_source_code_location_as_global(p, proc_name, pos);
 		}
 		}
 	case ParameterValue_Value:
 	case ParameterValue_Value:
 		return cg_build_expr(p, param_value.ast_value);
 		return cg_build_expr(p, param_value.ast_value);

+ 218 - 55
src/tilde_stmt.cpp

@@ -65,7 +65,7 @@ gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_vol
 	return cg_value(tb_inst_load(p->func, dt, the_ptr, alignment, is_volatile), type);
 	return cg_value(tb_inst_load(p->func, dt, the_ptr, alignment, is_volatile), type);
 }
 }
 
 
-gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile) {
+gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue src, bool is_volatile) {
 	GB_ASSERT_MSG(dst.kind != cgValue_Multi, "cannot store to multiple values at once");
 	GB_ASSERT_MSG(dst.kind != cgValue_Multi, "cannot store to multiple values at once");
 
 
 	if (dst.kind == cgValue_Addr) {
 	if (dst.kind == cgValue_Addr) {
@@ -122,10 +122,14 @@ gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src,
 		return;
 		return;
 	}
 	}
 
 
+
 	switch (dst.kind) {
 	switch (dst.kind) {
 	case cgValue_Value:
 	case cgValue_Value:
-		switch (dst.kind) {
+		switch (src.kind) {
 		case cgValue_Value:
 		case cgValue_Value:
+			if (src.node->dt.type == TB_INT && src.node->dt.data == 1) {
+				src.node = tb_inst_zxt(p->func, src.node, dt);
+			}
 			tb_inst_store(p->func, dt, dst.node, src.node, alignment, is_volatile);
 			tb_inst_store(p->func, dt, dst.node, src.node, alignment, is_volatile);
 			return;
 			return;
 		case cgValue_Addr:
 		case cgValue_Addr:
@@ -367,8 +371,7 @@ gb_internal cgValue cg_emit_ptr_offset(cgProcedure *p, cgValue ptr, cgValue inde
 
 
 	Type *elem = type_deref(ptr.type, true);
 	Type *elem = type_deref(ptr.type, true);
 	i64 stride = type_size_of(elem);
 	i64 stride = type_size_of(elem);
-	ptr.node = tb_inst_array_access(p->func, ptr.node, index.node, stride);
-	return ptr;
+	return cg_value(tb_inst_array_access(p->func, ptr.node, index.node, stride), alloc_type_pointer(elem));
 }
 }
 gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) {
 gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) {
 	GB_ASSERT(s.kind == cgValue_Value);
 	GB_ASSERT(s.kind == cgValue_Value);
@@ -383,8 +386,7 @@ gb_internal cgValue cg_emit_array_ep(cgProcedure *p, cgValue s, cgValue index) {
 
 
 	Type *elem = base_array_type(st);
 	Type *elem = base_array_type(st);
 	i64 stride = type_size_of(elem);
 	i64 stride = type_size_of(elem);
-	s.node = tb_inst_array_access(p->func, s.node, index.node, stride);
-	return s;
+	return cg_value(tb_inst_array_access(p->func, s.node, index.node, stride), alloc_type_pointer(elem));
 }
 }
 gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index) {
 gb_internal cgValue cg_emit_array_epi(cgProcedure *p, cgValue s, i64 index) {
 	return cg_emit_array_ep(p, s, cg_const_int(p, t_int, index));
 	return cg_emit_array_ep(p, s, cg_const_int(p, t_int, index));
@@ -425,7 +427,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
 	case Type_Slice:
 	case Type_Slice:
 		switch (index) {
 		switch (index) {
 		case 0:
 		case 0:
-			result_type = alloc_type_pointer(t->Slice.elem);
+			result_type = alloc_type_multi_pointer(t->Slice.elem);
 			offset = 0;
 			offset = 0;
 			break;
 			break;
 		case 1:
 		case 1:
@@ -439,7 +441,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
 		case Basic_string:
 		case Basic_string:
 			switch (index) {
 			switch (index) {
 			case 0:
 			case 0:
-				result_type = t_u8_ptr;
+				result_type = t_u8_multi_ptr;
 				offset = 0;
 				offset = 0;
 				break;
 				break;
 			case 1:
 			case 1:
@@ -494,7 +496,7 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
 	case Type_DynamicArray:
 	case Type_DynamicArray:
 		switch (index) {
 		switch (index) {
 		case 0:
 		case 0:
-			result_type = alloc_type_pointer(t->DynamicArray.elem);
+			result_type = alloc_type_multi_pointer(t->DynamicArray.elem);
 			offset = index*int_size;
 			offset = index*int_size;
 			break;
 			break;
 		case 1: case 2:
 		case 1: case 2:
@@ -564,6 +566,14 @@ gb_internal cgValue cg_emit_struct_ep(cgProcedure *p, cgValue s, i64 index) {
 	);
 	);
 }
 }
 
 
+
+gb_internal cgValue cg_emit_struct_ev(cgProcedure *p, cgValue s, i64 index) {
+	s = cg_address_from_load_or_generate_local(p, s);
+	cgValue ptr = cg_emit_struct_ep(p, s, index);
+	return cg_flatten_value(p, cg_emit_load(p, ptr));
+}
+
+
 gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel) {
 gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection const &sel) {
 	GB_ASSERT(sel.index.count > 0);
 	GB_ASSERT(sel.index.count > 0);
 	Type *type = type_deref(e.type);
 	Type *type = type_deref(e.type);
@@ -1008,7 +1018,7 @@ gb_internal void cg_build_assign_stmt(cgProcedure *p, AstAssignStmt *as) {
 	}
 	}
 }
 }
 
 
-gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return_results) {
+gb_internal void cg_build_return_stmt_internal(cgProcedure *p, Slice<cgValue> const &results) {
 	TypeTuple *tuple  = &p->type->Proc.results->Tuple;
 	TypeTuple *tuple  = &p->type->Proc.results->Tuple;
 	isize return_count = p->type->Proc.result_count;
 	isize return_count = p->type->Proc.result_count;
 
 
@@ -1016,38 +1026,6 @@ gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return
 		tb_inst_ret(p->func, 0, nullptr);
 		tb_inst_ret(p->func, 0, nullptr);
 		return;
 		return;
 	}
 	}
-	TEMPORARY_ALLOCATOR_GUARD();
-
-	auto results = array_make<cgValue>(temporary_allocator(), 0, return_count);
-
-	if (return_results.count != 0) {
-		for (isize i = 0; i < return_results.count; i++) {
-			cgValue res = cg_build_expr(p, return_results[i]);
-			cg_append_tuple_values(p, &results, res);
-		}
-	} else {
-		for_array(i, tuple->variables) {
-			Entity *e = tuple->variables[i];
-			cgAddr addr = map_must_get(&p->variable_map, e);
-			cgValue res = cg_addr_load(p, addr);
-			array_add(&results, res);
-		}
-	}
-	GB_ASSERT(results.count == return_count);
-
-	if (return_results.count != 0 && p->type->Proc.has_named_results) {
-		// NOTE(bill): store the named values before returning
-		for_array(i, tuple->variables) {
-			Entity *e = tuple->variables[i];
-			cgAddr addr = map_must_get(&p->variable_map, e);
-			cg_addr_store(p, addr, results[i]);
-		}
-	}
-	for_array(i, tuple->variables) {
-		Entity *e = tuple->variables[i];
-		results[i] = cg_emit_conv(p, results[i], e->type);
-	}
-
 
 
 	if (p->split_returns_index >= 0) {
 	if (p->split_returns_index >= 0) {
 		GB_ASSERT(is_calling_convention_odin(p->type->Proc.calling_convention));
 		GB_ASSERT(is_calling_convention_odin(p->type->Proc.calling_convention));
@@ -1071,15 +1049,20 @@ gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return
 			GB_ASSERT(p->proto->return_count == 1);
 			GB_ASSERT(p->proto->return_count == 1);
 			TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
 			TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
 
 
-			cgValue result = cg_flatten_value(p, results[0]);
+			cgValue result = results[return_count-1];
+			result = cg_flatten_value(p, result);
 			TB_Node *final_res = nullptr;
 			TB_Node *final_res = nullptr;
 			if (result.kind == cgValue_Addr) {
 			if (result.kind == cgValue_Addr) {
 				TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
 				TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
 				final_res = tb_inst_load(p->func, dt, result.node, align, false);
 				final_res = tb_inst_load(p->func, dt, result.node, align, false);
 			} else {
 			} else {
 				GB_ASSERT(result.kind == cgValue_Value);
 				GB_ASSERT(result.kind == cgValue_Value);
-				if (result.node->dt.raw == dt.raw) {
+				TB_DataType st = result.node->dt;
+				GB_ASSERT(st.type == dt.type);
+				if (st.raw == dt.raw) {
 					final_res = result.node;
 					final_res = result.node;
+				} else if (st.type == TB_INT && st.data == 1) {
+					final_res = tb_inst_zxt(p->func, result.node, dt);
 				} else {
 				} else {
 					final_res = tb_inst_bitcast(p->func, result.node, dt);
 					final_res = tb_inst_bitcast(p->func, result.node, dt);
 				}
 				}
@@ -1092,10 +1075,94 @@ gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return
 
 
 	} else {
 	} else {
 		GB_ASSERT(!is_calling_convention_odin(p->type->Proc.calling_convention));
 		GB_ASSERT(!is_calling_convention_odin(p->type->Proc.calling_convention));
+
+		if (p->return_by_ptr) {
+			Entity *e = tuple->variables[return_count-1];
+			TB_Node *ret_ptr = tb_inst_param(p->func, 0);
+			cgValue ptr = cg_value(ret_ptr, alloc_type_pointer(e->type));
+			cg_emit_store(p, ptr, results[return_count-1]);
+
+			tb_inst_ret(p->func, 0, nullptr);
+			return;
+		} else {
+			GB_ASSERT(p->proto->return_count == 1);
+			TB_DataType dt = TB_PROTOTYPE_RETURNS(p->proto)->dt;
+			if (results.count == 1) {
+				cgValue result = results[0];
+				result = cg_flatten_value(p, result);
+
+				TB_Node *final_res = nullptr;
+				if (result.kind == cgValue_Addr) {
+					TB_CharUnits align = cast(TB_CharUnits)type_align_of(result.type);
+					final_res = tb_inst_load(p->func, dt, result.node, align, false);
+				} else {
+					GB_ASSERT(result.kind == cgValue_Value);
+					TB_DataType st = result.node->dt;
+					GB_ASSERT(st.type == dt.type);
+					if (st.raw == dt.raw) {
+						final_res = result.node;
+					} else if (st.type == TB_INT && st.data == 1) {
+						final_res = tb_inst_zxt(p->func, result.node, dt);
+					} else {
+						final_res = tb_inst_bitcast(p->func, result.node, dt);
+					}
+				}
+
+				GB_ASSERT(final_res != nullptr);
+
+				tb_inst_ret(p->func, 1, &final_res);
+				return;
+			} else {
+				GB_ASSERT_MSG(results.count == 1, "TODO(bill): multi-return values for the return");
+				return;
+			}
+		}
+
 	}
 	}
+}
+
+
+gb_internal void cg_build_return_stmt(cgProcedure *p, Slice<Ast *> const &return_results) {
+	TypeTuple *tuple  = &p->type->Proc.results->Tuple;
+	isize return_count = p->type->Proc.result_count;
 
 
+	if (return_count == 0) {
+		tb_inst_ret(p->func, 0, nullptr);
+		return;
+	}
+	TEMPORARY_ALLOCATOR_GUARD();
 
 
-	GB_PANIC("TODO(bill): %.*s MUTLIPLE RETURN VALUES %td %td", LIT(p->name), results.count, return_results.count);
+	auto results = array_make<cgValue>(temporary_allocator(), 0, return_count);
+
+	if (return_results.count != 0) {
+		for (isize i = 0; i < return_results.count; i++) {
+			cgValue res = cg_build_expr(p, return_results[i]);
+			cg_append_tuple_values(p, &results, res);
+		}
+	} else {
+		for_array(i, tuple->variables) {
+			Entity *e = tuple->variables[i];
+			cgAddr addr = map_must_get(&p->variable_map, e);
+			cgValue res = cg_addr_load(p, addr);
+			array_add(&results, res);
+		}
+	}
+	GB_ASSERT(results.count == return_count);
+
+	if (return_results.count != 0 && p->type->Proc.has_named_results) {
+		// NOTE(bill): store the named values before returning
+		for_array(i, tuple->variables) {
+			Entity *e = tuple->variables[i];
+			cgAddr addr = map_must_get(&p->variable_map, e);
+			cg_addr_store(p, addr, results[i]);
+		}
+	}
+	for_array(i, tuple->variables) {
+		Entity *e = tuple->variables[i];
+		results[i] = cg_emit_conv(p, results[i], e->type);
+	}
+
+	cg_build_return_stmt_internal(p, slice_from_array(results));
 }
 }
 
 
 gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
 gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
@@ -1673,13 +1740,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 
 
 	// TODO(bill): check if last instruction was a terminating one or not
 	// TODO(bill): check if last instruction was a terminating one or not
 
 
-	{
-		TokenPos pos = ast_token(node).pos;
-		TB_FileID *file_id = map_get(&p->module->file_id_map, cast(uintptr)pos.file_id);
-		if (file_id) {
-			tb_inst_set_location(p->func, *file_id, pos.line);
-		}
-	}
+	cg_set_debug_pos_from_node(p, node);
 
 
 	u16 prev_state_flags = p->state_flags;
 	u16 prev_state_flags = p->state_flags;
 	defer (p->state_flags = prev_state_flags);
 	defer (p->state_flags = prev_state_flags);
@@ -1838,7 +1899,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 	case_end;
 	case_end;
 
 
 	case_ast_node(rs, RangeStmt, node);
 	case_ast_node(rs, RangeStmt, node);
-		GB_PANIC("TODO(bill): cg_build_range_stmt");
+		GB_PANIC("TODO(bill): cg_build_range_stmt %.*s", LIT(p->name));
 		// cg_build_range_stmt(p, rs, rs->scope);
 		// cg_build_range_stmt(p, rs, rs->scope);
 	case_end;
 	case_end;
 
 
@@ -1879,13 +1940,115 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 	}
 	}
 }
 }
 
 
+gb_internal void cg_build_constant_value_decl(cgProcedure *p, AstValueDecl *vd) {
+	if (vd == nullptr || vd->is_mutable) {
+		return;
+	}
+
+	auto *min_dep_set = &p->module->info->minimum_dependency_set;
+
+	static i32 global_guid = 0;
+
+	for (Ast *ident : vd->names) {
+		GB_ASSERT(ident->kind == Ast_Ident);
+		Entity *e = entity_of_node(ident);
+		GB_ASSERT(e != nullptr);
+		if (e->kind != Entity_TypeName) {
+			continue;
+		}
+
+		bool polymorphic_struct = false;
+		if (e->type != nullptr && e->kind == Entity_TypeName) {
+			Type *bt = base_type(e->type);
+			if (bt->kind == Type_Struct) {
+				polymorphic_struct = bt->Struct.is_polymorphic;
+			}
+		}
+
+		if (!polymorphic_struct && !ptr_set_exists(min_dep_set, e)) {
+			continue;
+		}
+
+		if (e->TypeName.ir_mangled_name.len != 0) {
+			// NOTE(bill): Already set
+			continue;
+		}
+
+		cg_set_nested_type_name_ir_mangled_name(e, p);
+	}
+
+	for_array(i, vd->names) {
+		Ast *ident = vd->names[i];
+		GB_ASSERT(ident->kind == Ast_Ident);
+		Entity *e = entity_of_node(ident);
+		GB_ASSERT(e != nullptr);
+		if (e->kind != Entity_Procedure) {
+			continue;
+		}
+		GB_ASSERT (vd->values[i] != nullptr);
+
+		Ast *value = unparen_expr(vd->values[i]);
+		if (value->kind != Ast_ProcLit) {
+			continue; // It's an alias
+		}
+
+		DeclInfo *decl = decl_info_of_entity(e);
+		ast_node(pl, ProcLit, decl->proc_lit);
+		if (pl->body != nullptr) {
+			GenProcsData *gpd = e->Procedure.gen_procs;
+			if (gpd) {
+				rw_mutex_shared_lock(&gpd->mutex);
+				for (Entity *e : gpd->procs) {
+					if (!ptr_set_exists(min_dep_set, e)) {
+						continue;
+					}
+					DeclInfo *d = decl_info_of_entity(e);
+					cg_build_nested_proc(p, &d->proc_lit->ProcLit, e);
+				}
+				rw_mutex_shared_unlock(&gpd->mutex);
+			} else {
+				cg_build_nested_proc(p, pl, e);
+			}
+		} else {
+
+			// FFI - Foreign function interace
+			String original_name = e->token.string;
+			String name = original_name;
+
+			if (e->Procedure.is_foreign) {
+				GB_PANIC("cg_add_foreign_library_path");
+				// cg_add_foreign_library_path(p->module, e->Procedure.foreign_library);
+			}
+
+			if (e->Procedure.link_name.len > 0) {
+				name = e->Procedure.link_name;
+			}
+
+			cgValue *prev_value = string_map_get(&p->module->members, name);
+			if (prev_value != nullptr) {
+				// NOTE(bill): Don't do mutliple declarations in the IR
+				return;
+			}
+
+			e->Procedure.link_name = name;
+
+			cgProcedure *nested_proc = cg_procedure_create(p->module, e);
+
+			cgValue value = p->value;
+
+			array_add(&p->module->procedures_to_generate, nested_proc);
+			array_add(&p->children, nested_proc);
+			string_map_set(&p->module->members, name, value);
+		}
+	}
+}
+
 
 
 gb_internal void cg_build_stmt_list(cgProcedure *p, Slice<Ast *> const &stmts) {
 gb_internal void cg_build_stmt_list(cgProcedure *p, Slice<Ast *> const &stmts) {
 	for (Ast *stmt : stmts) {
 	for (Ast *stmt : stmts) {
 		switch (stmt->kind) {
 		switch (stmt->kind) {
 		case_ast_node(vd, ValueDecl, stmt);
 		case_ast_node(vd, ValueDecl, stmt);
-			// TODO(bill)
-			// cg_build_constant_value_decl(p, vd);
+			cg_build_constant_value_decl(p, vd);
 		case_end;
 		case_end;
 		case_ast_node(fb, ForeignBlockDecl, stmt);
 		case_ast_node(fb, ForeignBlockDecl, stmt);
 			ast_node(block, BlockStmt, fb->body);
 			ast_node(block, BlockStmt, fb->body);

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