Browse Source

Fix dependency issue; Allow polymorphic procedures in tilde

gingerBill 2 years ago
parent
commit
0f217c715e
7 changed files with 233 additions and 175 deletions
  1. 2 1
      src/check_expr.cpp
  2. 2 1
      src/tilde.hpp
  3. 10 1
      src/tilde_debug.cpp
  4. 137 141
      src/tilde_expr.cpp
  5. 34 21
      src/tilde_proc.cpp
  6. 28 0
      src/tilde_stmt.cpp
  7. 20 10
      src/types.cpp

+ 2 - 1
src/check_expr.cpp

@@ -5985,8 +5985,8 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera
 	}
 	}
 
 
 	Entity *entity_to_use = data->gen_entity != nullptr ? data->gen_entity : e;
 	Entity *entity_to_use = data->gen_entity != nullptr ? data->gen_entity : e;
+	add_entity_use(c, ident, entity_to_use);
 	if (!return_on_failure && entity_to_use != nullptr) {
 	if (!return_on_failure && entity_to_use != nullptr) {
-		add_entity_use(c, ident, entity_to_use);
 		update_untyped_expr_type(c, operand->expr, entity_to_use->type, true);
 		update_untyped_expr_type(c, operand->expr, entity_to_use->type, true);
 		add_type_and_value(c, operand->expr, operand->mode, entity_to_use->type, operand->value);
 		add_type_and_value(c, operand->expr, operand->mode, entity_to_use->type, operand->value);
 	}
 	}
@@ -7174,6 +7174,7 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c
 				c->decl->defer_used += 1;
 				c->decl->defer_used += 1;
 			}
 			}
 		}
 		}
+		add_entity_use(c, operand->expr, initial_entity);
 	}
 	}
 
 
 	if (operand->mode != Addressing_ProcGroup) {
 	if (operand->mode != Addressing_ProcGroup) {

+ 2 - 1
src/tilde.hpp

@@ -309,7 +309,8 @@ 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 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 cgAddr  cg_add_global(cgProcedure *p, Type *type, Entity *e);
 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);
 
 

+ 10 - 1
src/tilde_debug.cpp

@@ -76,9 +76,18 @@ gb_internal TB_DebugType *cg_debug_type_internal_record(cgModule *m, Type *type,
 			type_set_offsets(bt);
 			type_set_offsets(bt);
 
 
 			TB_DebugType *record = tb_debug_create_struct(m->mod, 0, "");
 			TB_DebugType *record = tb_debug_create_struct(m->mod, 0, "");
-			TB_DebugType **fields = tb_debug_record_begin(record, bt->Tuple.variables.count);
+			isize record_count = 0;
+			for (Entity *e : bt->Tuple.variables) {
+				if (e->kind == Entity_Variable) {
+					record_count += 1;
+				}
+			}
+			TB_DebugType **fields = tb_debug_record_begin(record, record_count);
 			for_array(i, bt->Tuple.variables) {
 			for_array(i, bt->Tuple.variables) {
 				Entity *e = bt->Tuple.variables[i];
 				Entity *e = bt->Tuple.variables[i];
+				if (e->kind != Entity_Variable) {
+					continue;
+				}
 				Type *type = e->type;
 				Type *type = e->type;
 				if (is_type_proc(type)) {
 				if (is_type_proc(type)) {
 					type = t_rawptr;
 					type = t_rawptr;

+ 137 - 141
src/tilde_expr.cpp

@@ -2399,7 +2399,12 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 	Type *type = type_of_expr(expr);
 	Type *type = type_of_expr(expr);
 	Type *bt = base_type(type);
 	Type *bt = base_type(type);
 
 
-	cgAddr v = cg_add_local(p, type, nullptr, true);
+	cgAddr v = {};
+	if (p->is_startup) {
+		v = cg_add_global(p, type, nullptr);
+	} else {
+		v = cg_add_local(p, type, nullptr, true);
+	}
 
 
 	if (cl->elems.count == 0) {
 	if (cl->elems.count == 0) {
 		// No need to create it
 		// No need to create it
@@ -2424,8 +2429,6 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 	}
 	}
 	TokenPos pos = ast_token(expr).pos;
 	TokenPos pos = ast_token(expr).pos;
 
 
-	if (cl->elems.count == 0) {
-	}
 
 
 	switch (bt->kind) {
 	switch (bt->kind) {
 	default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
 	default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
@@ -2493,21 +2496,22 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 		return v;
 		return v;
 	}
 	}
 
 
-	// case Type_Map: {
-	// 	GB_ASSERT(!build_context.no_dynamic_literals);
+	case Type_Map: {
+		GB_ASSERT(!build_context.no_dynamic_literals);
+		GB_PANIC("TODO(bill): map literals");
 
 
-	// 	cgValue err = cg_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
-	// 	gb_unused(err);
+		// cgValue err = cg_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
+		// gb_unused(err);
 
 
-	// 	for (Ast *elem : cl->elems) {
-	// 		ast_node(fv, FieldValue, elem);
+		// for (Ast *elem : cl->elems) {
+		// 	ast_node(fv, FieldValue, elem);
 
 
-	// 		cgValue key   = cg_build_expr(p, fv->field);
-	// 		cgValue value = cg_build_expr(p, fv->value);
-	// 		cg_internal_dynamic_map_set(p, v.addr, type, key, value, elem);
-	// 	}
-	// 	break;
-	// }
+		// 	cgValue key   = cg_build_expr(p, fv->field);
+		// 	cgValue value = cg_build_expr(p, fv->value);
+		// 	cg_internal_dynamic_map_set(p, v.addr, type, key, value, elem);
+		// }
+		break;
+	}
 
 
 	case Type_Array: {
 	case Type_Array: {
 		auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 		auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
@@ -2523,23 +2527,21 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 		assign_array(p, temp_data);
 		assign_array(p, temp_data);
 		break;
 		break;
 	}
 	}
-	// case Type_EnumeratedArray: {
-	// 	cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr)));
-
-	// 	auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+	case Type_EnumeratedArray: {
+		auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
 
-	// 	populate(p, cl->elems, &temp_data, type);
+		populate(p, cl->elems, &temp_data, type);
 
 
-	// 	cgValue dst_ptr = cg_addr_get_ptr(p, v);
-	// 	i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value);
-	// 	for_array(i, temp_data) {
-	// 		i32 index = cast(i32)(temp_data[i].elem_index - index_offset);
-	// 		temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index);
-	// 	}
+		cgValue dst_ptr = cg_addr_get_ptr(p, v);
+		i64 index_offset = exact_value_to_i64(*bt->EnumeratedArray.min_value);
+		for_array(i, temp_data) {
+			i32 index = cast(i32)(temp_data[i].elem_index - index_offset);
+			temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, index);
+		}
 
 
-	// 	assign_array(p, temp_data);
-	// 	break;
-	// }
+		assign_array(p, temp_data);
+		break;
+	}
 	case Type_Slice: {
 	case Type_Slice: {
 		isize count = gb_max(cl->elems.count, cl->max_count);
 		isize count = gb_max(cl->elems.count, cl->max_count);
 
 
@@ -2570,88 +2572,89 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 		return v;
 		return v;
 	}
 	}
 
 
-	// case Type_DynamicArray: {
-	// 	GB_ASSERT(!build_context.no_dynamic_literals);
+	case Type_DynamicArray: {
+		GB_ASSERT(!build_context.no_dynamic_literals);
 
 
-	// 	Type *et = bt->DynamicArray.elem;
-	// 	cgValue size  = cg_const_int(p->module, t_int, type_size_of(et));
-	// 	cgValue align = cg_const_int(p->module, t_int, type_align_of(et));
+		Type *et = bt->DynamicArray.elem;
+		cgValue size  = cg_const_int(p, t_int, type_size_of(et));
+		cgValue align = cg_const_int(p, t_int, type_align_of(et));
 
 
-	// 	i64 item_count = gb_max(cl->max_count, cl->elems.count);
-	// 	{
+		i64 item_count = gb_max(cl->max_count, cl->elems.count);
+		{
 
 
-	// 		auto args = array_make<cgValue>(temporary_allocator(), 5);
-	// 		args[0] = cg_emit_conv(p, cg_addr_get_ptr(p, v), t_rawptr);
-	// 		args[1] = size;
-	// 		args[2] = align;
-	// 		args[3] = cg_const_int(p->module, t_int, item_count);
-	// 		args[4] = cg_emit_source_code_location_as_global(p, proc_name, pos);
-	// 		cg_emit_runtime_call(p, "__dynamic_array_reserve", args);
-	// 	}
+			auto args = slice_make<cgValue>(temporary_allocator(), 5);
+			args[0] = cg_emit_conv(p, cg_addr_get_ptr(p, v), t_rawptr);
+			args[1] = size;
+			args[2] = align;
+			args[3] = cg_const_int(p, t_int, item_count);
+			args[4] = cg_emit_source_code_location_as_global(p, proc_name, pos);
+			cg_emit_runtime_call(p, "__dynamic_array_reserve", args);
+		}
 
 
-	// 	cgValue items = cg_generate_local_array(p, et, item_count);
+		Type *array_type = alloc_type_array(et, item_count);
+		cgAddr items_addr = cg_add_local(p, array_type, nullptr, true);
+		cgValue items = cg_addr_get_ptr(p, items_addr);
 
 
-	// 	auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-	// 	populate(p, cl->elems, &temp_data, type);
+		auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+		populate(p, cl->elems, &temp_data, type);
 
 
-	// 	for_array(i, temp_data) {
-	// 		temp_data[i].gep = cg_emit_array_epi(p, items, temp_data[i].elem_index);
-	// 	}
-	// 	assign_array(p, temp_data);
-
-	// 	{
-	// 		auto args = array_make<cgValue>(temporary_allocator(), 6);
-	// 		args[0] = cg_emit_conv(p, v.addr, t_rawptr);
-	// 		args[1] = size;
-	// 		args[2] = align;
-	// 		args[3] = cg_emit_conv(p, items, t_rawptr);
-	// 		args[4] = cg_const_int(p->module, t_int, item_count);
-	// 		args[5] = cg_emit_source_code_location_as_global(p, proc_name, pos);
-	// 		cg_emit_runtime_call(p, "__dynamic_array_append", args);
-	// 	}
-	// 	break;
-	// }
+		for_array(i, temp_data) {
+			temp_data[i].gep = cg_emit_array_epi(p, items, temp_data[i].elem_index);
+		}
+		assign_array(p, temp_data);
 
 
-	// case Type_Basic: {
-	// 	GB_ASSERT(is_type_any(bt));
-	// 	cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr)));
-	// 	String field_names[2] = {
-	// 		str_lit("data"),
-	// 		str_lit("id"),
-	// 	};
-	// 	Type *field_types[2] = {
-	// 		t_rawptr,
-	// 		t_typeid,
-	// 	};
-
-	// 	for_array(field_index, cl->elems) {
-	// 		Ast *elem = cl->elems[field_index];
-
-	// 		cgValue field_expr = {};
-	// 		isize index = field_index;
-
-	// 		if (elem->kind == Ast_FieldValue) {
-	// 			ast_node(fv, FieldValue, elem);
-	// 			Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
-	// 			index = sel.index[0];
-	// 			elem = fv->value;
-	// 		} else {
-	// 			TypeAndValue tav = type_and_value_of_expr(elem);
-	// 			Selection sel = lookup_field(bt, field_names[field_index], false);
-	// 			index = sel.index[0];
-	// 		}
-
-	// 		field_expr = cg_build_expr(p, elem);
-
-	// 		GB_ASSERT(field_expr.type->kind != Type_Tuple);
-
-	// 		Type *ft = field_types[index];
-	// 		cgValue fv = cg_emit_conv(p, field_expr, ft);
-	// 		cgValue gep = cg_emit_struct_ep(p, cg_addr_get_ptr(p, v), cast(i32)index);
-	// 		cg_emit_store(p, gep, fv);
-	// 	}
-	// 	break;
-	// }
+		{
+			auto args = slice_make<cgValue>(temporary_allocator(), 6);
+			args[0] = cg_emit_conv(p, v.addr, t_rawptr);
+			args[1] = size;
+			args[2] = align;
+			args[3] = cg_emit_conv(p, items, t_rawptr);
+			args[4] = cg_const_int(p, t_int, item_count);
+			args[5] = cg_emit_source_code_location_as_global(p, proc_name, pos);
+			cg_emit_runtime_call(p, "__dynamic_array_append", args);
+		}
+		break;
+	}
+
+	case Type_Basic: {
+		GB_ASSERT(is_type_any(bt));
+		String field_names[2] = {
+			str_lit("data"),
+			str_lit("id"),
+		};
+		Type *field_types[2] = {
+			t_rawptr,
+			t_typeid,
+		};
+
+		for_array(field_index, cl->elems) {
+			Ast *elem = cl->elems[field_index];
+
+			cgValue field_expr = {};
+			isize index = field_index;
+
+			if (elem->kind == Ast_FieldValue) {
+				ast_node(fv, FieldValue, elem);
+				Selection sel = lookup_field(bt, fv->field->Ident.token.string, false);
+				index = sel.index[0];
+				elem = fv->value;
+			} else {
+				TypeAndValue tav = type_and_value_of_expr(elem);
+				Selection sel = lookup_field(bt, field_names[field_index], false);
+				index = sel.index[0];
+			}
+
+			field_expr = cg_build_expr(p, elem);
+
+			GB_ASSERT(field_expr.type->kind != Type_Tuple);
+
+			Type *ft = field_types[index];
+			cgValue fv = cg_emit_conv(p, field_expr, ft);
+			cgValue gep = cg_emit_struct_ep(p, cg_addr_get_ptr(p, v), index);
+			cg_emit_store(p, gep, fv);
+		}
+		break;
+	}
 
 
 	case Type_BitSet: {
 	case Type_BitSet: {
 		i64 sz = type_size_of(type);
 		i64 sz = type_size_of(type);
@@ -2679,48 +2682,41 @@ cgAddr cg_build_addr_compound_lit(cgProcedure *p, Ast *expr) {
 		return v;
 		return v;
 	}
 	}
 
 
-	// case Type_Matrix: {
-	// 	cg_addr_store(p, v, cg_const_value(p->module, type, exact_value_compound(expr)));
+	case Type_Matrix: {
+		auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
 
-	// 	auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
+		populate(p, cl->elems, &temp_data, type);
 
 
-	// 	populate(p, cl->elems, &temp_data, type);
+		cgValue dst_ptr = cg_addr_get_ptr(p, v);
+		for_array(i, temp_data) {
+			temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, temp_data[i].elem_index);
+		}
 
 
-	// 	cgValue dst_ptr = cg_addr_get_ptr(p, v);
-	// 	for_array(i, temp_data) {
-	// 		temp_data[i].gep = cg_emit_array_epi(p, dst_ptr, temp_data[i].elem_index);
-	// 	}
+		assign_array(p, temp_data);
+		break;
+	}
 
 
-	// 	assign_array(p, temp_data);
-	// 	break;
-	// }
+	case Type_SimdVector: {
+		// auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
 
 
-	// case Type_SimdVector: {
-	// 	cgValue vector_value = cg_const_value(p->module, type, exact_value_compound(expr));
-	// 	defer (cg_addr_store(p, v, vector_value));
-
-	// 	auto temp_data = array_make<cgCompoundLitElemTempData>(temporary_allocator(), 0, cl->elems.count);
-
-	// 	populate(p, cl->elems, &temp_data, type);
-
-	// 	// TODO(bill): reduce the need for individual `insertelement` if a `shufflevector`
-	// 	// might be a better option
-	// 	for (auto const &td : temp_data) {
-	// 		if (td.value.value != nullptr) {
-	// 			if (td.elem_length > 0) {
-	// 				for (i64 k = 0; k < td.elem_length; k++) {
-	// 					LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index + k).value;
-	// 					vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, "");
-	// 				}
-	// 			} else {
-	// 				LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index).value;
-	// 				vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, "");
-
-	// 			}
-	// 		}
-	// 	}
-	// 	break;
-	// }
+		// populate(p, cl->elems, &temp_data, type);
+
+		// // TODO(bill): reduce the need for individual `insertelement` if a `shufflevector`
+		// // might be a better option
+		// for (auto const &td : temp_data) if (td.value.node != nullptr) {
+		// 	if (td.elem_length > 0) {
+		// 		for (i64 k = 0; k < td.elem_length; k++) {
+		// 			LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index + k).value;
+		// 			vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, "");
+		// 		}
+		// 	} else {
+		// 		LLVMValueRef index = cg_const_int(p->module, t_u32, td.elem_index).value;
+		// 		vector_value.value = LLVMBuildInsertElement(p->builder, vector_value.value, td.value.value, index, "");
+
+		// 	}
+		// }
+		break;
+	}
 	}
 	}
 
 
 	return v;
 	return v;

+ 34 - 21
src/tilde_proc.cpp

@@ -582,8 +582,13 @@ gb_internal cgValue cg_emit_call(cgProcedure * p, cgValue value, Slice<cgValue>
 			params[param_index++] = local;
 			params[param_index++] = local;
 		}
 		}
 	}
 	}
+	isize param_entity_index = 0;
 	for_array(i, args) {
 	for_array(i, args) {
-		Type *param_type = param_entities[i]->type;
+		Entity *param_entity = nullptr;
+		do {
+			param_entity = param_entities[param_entity_index++];
+		} while (param_entity->kind != Entity_Variable);
+		Type *param_type = param_entity->type;
 		cgValue arg = args[i];
 		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);
@@ -839,7 +844,15 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) {
 
 
 	GB_ASSERT(ce->split_args != nullptr);
 	GB_ASSERT(ce->split_args != nullptr);
 
 
-	auto args = array_make<cgValue>(temporary_allocator(), 0, pt->param_count);
+	isize internal_param_count = 0;
+	if (pt->params) for (Entity *e : pt->params->Tuple.variables) {
+		if (e->kind == Entity_Variable) {
+			internal_param_count += 1;
+		}
+	}
+	GB_ASSERT(internal_param_count <= pt->param_count);
+
+	auto args = array_make<cgValue>(temporary_allocator(), 0, internal_param_count);
 
 
 	bool vari_expand = (ce->ellipsis.pos.line != 0);
 	bool vari_expand = (ce->ellipsis.pos.line != 0);
 	bool is_c_vararg = pt->c_vararg;
 	bool is_c_vararg = pt->c_vararg;
@@ -918,7 +931,7 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) {
 	}
 	}
 
 
 	if (!is_c_vararg) {
 	if (!is_c_vararg) {
-		array_resize(&args, pt->param_count);
+		array_resize(&args, internal_param_count);
 	}
 	}
 
 
 	for (Ast *arg : ce->split_args->named) {
 	for (Ast *arg : ce->split_args->named) {
@@ -938,39 +951,39 @@ gb_internal cgValue cg_build_call_expr_internal(cgProcedure *p, Ast *expr) {
 
 
 
 
 	if (pt->params != nullptr)  {
 	if (pt->params != nullptr)  {
-		isize min_count = pt->params->Tuple.variables.count;
+		isize min_count = internal_param_count;
 		if (is_c_vararg) {
 		if (is_c_vararg) {
 			min_count -= 1;
 			min_count -= 1;
 		}
 		}
-		GB_ASSERT(args.count >= min_count);
-		for_array(arg_index, pt->params->Tuple.variables) {
-			Entity *e = pt->params->Tuple.variables[arg_index];
-			if (pt->variadic && arg_index == pt->variadic_index) {
+		GB_ASSERT_MSG(args.count >= min_count, "in %.*s", LIT(p->name));
+		isize arg_index = 0;
+		for_array(param_index, pt->params->Tuple.variables) {
+			Entity *e = pt->params->Tuple.variables[param_index];
+			if (e->kind == Entity_TypeName) {
+				continue;
+			} else if (e->kind == Entity_Constant) {
+				continue;
+			}
+			GB_ASSERT(e->kind == Entity_Variable);
+
+			if (pt->variadic && param_index == pt->variadic_index) {
 				if (!is_c_vararg && args[arg_index].node == nullptr) {
 				if (!is_c_vararg && args[arg_index].node == nullptr) {
-					args[arg_index] = cg_const_nil(p, e->type);
+					args[arg_index++] = cg_const_nil(p, e->type);
 				}
 				}
 				continue;
 				continue;
 			}
 			}
 
 
 			cgValue arg = args[arg_index];
 			cgValue arg = args[arg_index];
 			if (arg.node == nullptr) {
 			if (arg.node == nullptr) {
-				switch (e->kind) {
-				case Entity_TypeName:
-				case Entity_Constant:
-					break;
-				case Entity_Variable:
-					args[arg_index] = cg_handle_param_value(p, e->type, e->Variable.param_value, pos);
-					break;
-				default:
-					GB_PANIC("Unknown entity kind %.*s\n", LIT(entity_strings[e->kind]));
-				}
+				GB_ASSERT(e->kind == Entity_Variable);
+				args[arg_index++] = cg_handle_param_value(p, e->type, e->Variable.param_value, pos);
 			} else {
 			} else {
-				args[arg_index] = cg_emit_conv(p, arg, e->type);
+				args[arg_index++] = cg_emit_conv(p, arg, e->type);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	isize final_count = is_c_vararg ? args.count : pt->param_count;
+	isize final_count = is_c_vararg ? args.count : internal_param_count;
 	auto call_args = slice(args, 0, final_count);
 	auto call_args = slice(args, 0, final_count);
 
 
 	return cg_emit_call(p, value, call_args);
 	return cg_emit_call(p, value, call_args);

+ 28 - 0
src/tilde_stmt.cpp

@@ -747,6 +747,34 @@ gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero
 	return addr;
 	return addr;
 }
 }
 
 
+gb_internal cgAddr cg_add_global(cgProcedure *p, Type *type, Entity *e) {
+	GB_ASSERT(type != nullptr);
+
+	isize size = type_size_of(type);
+	TB_CharUnits alignment = cast(TB_CharUnits)type_align_of(type);
+	if (is_type_matrix(type)) {
+		alignment *= 2; // NOTE(bill): Just in case
+	}
+
+	TB_Global *global = tb_global_create(p->module->mod, 0, "", nullptr, TB_LINKAGE_PRIVATE);
+	tb_global_set_storage(p->module->mod, tb_module_get_data(p->module->mod), global, size, alignment, 0);
+	TB_Node *local = tb_inst_get_symbol_address(p->func, cast(TB_Symbol *)global);
+
+	if (e != nullptr && e->token.string.len > 0 && e->token.string != "_") {
+		// NOTE(bill): for debugging purposes only
+		String name = e->token.string;
+		TB_DebugType *debug_type = cg_debug_type(p->module, type);
+		tb_node_append_attrib(local, tb_function_attrib_variable(p->func, name.len, cast(char const *)name.text, debug_type));
+	}
+
+	cgAddr addr = cg_addr(cg_value(local, alloc_type_pointer(type)));
+	if (e) {
+		map_set(&p->variable_map, e, addr);
+	}
+	return addr;
+}
+
+
 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) {
 	TB_CharUnits size  = cast(TB_CharUnits)type_size_of(original_type);
 	TB_CharUnits size  = cast(TB_CharUnits)type_size_of(original_type);
 	TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(original_type), min_alignment);
 	TB_CharUnits align = cast(TB_CharUnits)gb_max(type_align_of(original_type), min_alignment);

+ 20 - 10
src/types.cpp

@@ -3646,18 +3646,26 @@ gb_internal i64 *type_set_offsets_of(Slice<Entity *> const &fields, bool is_pack
 		}
 		}
 	} else if (is_packed) {
 	} else if (is_packed) {
 		for_array(i, fields) {
 		for_array(i, fields) {
-			i64 size = type_size_of(fields[i]->type);
-			offsets[i] = curr_offset;
-			curr_offset += size;
+			if (fields[i]->kind != Entity_Variable) {
+				offsets[i] = -1;
+			} else {
+				i64 size = type_size_of(fields[i]->type);
+				offsets[i] = curr_offset;
+				curr_offset += size;
+			}
 		}
 		}
 	} else {
 	} else {
 		for_array(i, fields) {
 		for_array(i, fields) {
-			Type *t = fields[i]->type;
-			i64 align = gb_max(type_align_of(t), 1);
-			i64 size  = gb_max(type_size_of( t), 0);
-			curr_offset = align_formula(curr_offset, align);
-			offsets[i] = curr_offset;
-			curr_offset += size;
+			if (fields[i]->kind != Entity_Variable) {
+				offsets[i] = -1;
+			} else {
+				Type *t = fields[i]->type;
+				i64 align = gb_max(type_align_of(t), 1);
+				i64 size  = gb_max(type_size_of( t), 0);
+				curr_offset = align_formula(curr_offset, align);
+				offsets[i] = curr_offset;
+				curr_offset += size;
+			}
 		}
 		}
 	}
 	}
 	return offsets;
 	return offsets;
@@ -3924,7 +3932,9 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) {
 		if (gb_is_between(index, 0, t->Tuple.variables.count-1)) {
 		if (gb_is_between(index, 0, t->Tuple.variables.count-1)) {
 			GB_ASSERT(t->Tuple.offsets != nullptr);
 			GB_ASSERT(t->Tuple.offsets != nullptr);
 			if (field_type_) *field_type_ = t->Tuple.variables[index]->type;
 			if (field_type_) *field_type_ = t->Tuple.variables[index]->type;
-			return t->Tuple.offsets[index];
+			i64 offset = t->Tuple.offsets[index];
+			GB_ASSERT(offset >= 0);
+			return offset;
 		}
 		}
 		break;
 		break;