Browse Source

Procedure literals for default values in structs

Ginger Bill 8 years ago
parent
commit
8f39ebbe5a
7 changed files with 202 additions and 95 deletions
  1. 4 6
      core/_preload.odin
  2. 2 6
      core/c.odin
  3. 26 11
      src/check_expr.cpp
  4. 8 0
      src/exact_value.cpp
  5. 66 30
      src/ir.cpp
  6. 95 42
      src/ir_print.cpp
  7. 1 0
      src/types.cpp

+ 4 - 6
core/_preload.odin

@@ -721,18 +721,16 @@ __mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #cc_con
 	when size_of(rawptr) == 8 {
 		foreign __llvm_core llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i64" ---;
 	} else {
-		foreign __llvm_core llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32";
+		foreign __llvm_core llvm_memcpy :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #link_name "llvm.memcpy.p0i8.p0i8.i32" ---;
 	}
 	llvm_memcpy(dst, src, len, 1, false);
 	return dst;
 }
 
 __mem_compare :: proc(a, b: ^u8, n: int) -> int #cc_contextless {
-	for i in 0..n {
-		switch {
-		case (a+i)^ < (b+i)^: return -1;
-		case (a+i)^ > (b+i)^: return +1;
-		}
+	for i in 0..n do switch {
+	case (a+i)^ < (b+i)^: return -1;
+	case (a+i)^ > (b+i)^: return +1;
 	}
 	return 0;
 }

+ 2 - 6
core/c.odin

@@ -13,17 +13,13 @@ c_ushort         :: i16;
 c_int            :: i32;
 c_uint           :: u32;
 
-when ODIN_OS == "windows" {
-	c_long :: i32;
-} else when size_of(int) == 4 {
+when ODIN_OS == "windows" || size_of(int) == 4 {
 	c_long :: i32;
 } else {
 	c_long :: i64;
 }
 
-when ODIN_OS == "windows" {
-	c_ulong :: u32;
-} else when size_of(uint) == 4 {
+when ODIN_OS == "windows" || size_of(uint) == 4 {
 	c_ulong :: u32;
 } else {
 	c_ulong :: u64;

+ 26 - 11
src/check_expr.cpp

@@ -1035,7 +1035,12 @@ Array<Entity *> check_struct_fields(Checker *c, AstNode *node, Array<AstNode *>
 			if (is_operand_nil(o)) {
 				default_is_nil = true;
 			} else if (o.mode != Addressing_Constant) {
-				error(default_value, "Default parameter must be a constant");
+				if (default_value->kind == AstNode_ProcLit) {
+					value = exact_value_procedure(default_value);
+					// error(default_value, "A procedure literal as a default param is not yet supported");
+				} else {
+					error(default_value, "Default parameter must be a constant");
+				}
 			} else {
 				value = o.value;
 			}
@@ -1329,10 +1334,10 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 		context = str_lit("struct #raw_union");
 	}
 
-	Type *polymorphic_params = nullptr;
-	bool is_polymorphic = false;
-	bool can_check_fields = true;
-	bool is_poly_specialized = false;
+	Type *polymorphic_params     = nullptr;
+	bool is_polymorphic          = false;
+	bool can_check_fields        = true;
+	bool is_poly_specialized     = false;
 
 	if (st->polymorphic_params != nullptr) {
 		ast_node(field_list, FieldList, st->polymorphic_params);
@@ -1481,12 +1486,12 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 		}
 	}
 
-	struct_type->Struct.scope               = c->context.scope;
-	struct_type->Struct.is_packed           = st->is_packed;
-	struct_type->Struct.is_ordered          = st->is_ordered;
-	struct_type->Struct.polymorphic_params  = polymorphic_params;
-	struct_type->Struct.is_polymorphic      = is_polymorphic;
-	struct_type->Struct.is_poly_specialized = is_poly_specialized;
+	struct_type->Struct.scope                   = c->context.scope;
+	struct_type->Struct.is_packed               = st->is_packed;
+	struct_type->Struct.is_ordered              = st->is_ordered;
+	struct_type->Struct.polymorphic_params      = polymorphic_params;
+	struct_type->Struct.is_polymorphic          = is_polymorphic;
+	struct_type->Struct.is_poly_specialized     = is_poly_specialized;
 
 	Array<Entity *> fields = {};
 
@@ -1497,6 +1502,16 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, Array<Opera
 	struct_type->Struct.fields              = fields;
 	struct_type->Struct.fields_in_src_order = fields;
 
+	for_array(i, fields) {
+		Entity *f = fields[i];
+		if (f->kind == Entity_Variable) {
+			if (f->Variable.default_value.kind == ExactValue_Procedure) {
+				struct_type->Struct.has_proc_default_values = true;
+				break;
+			}
+		}
+	}
+
 
 	if (!struct_type->Struct.is_raw_union) {
 		type_set_offsets(c->allocator, struct_type);

+ 8 - 0
src/exact_value.cpp

@@ -22,6 +22,7 @@ enum ExactValueKind {
 	ExactValue_Complex,
 	ExactValue_Pointer,
 	ExactValue_Compound, // TODO(bill): Is this good enough?
+	ExactValue_Procedure, // TODO(bill): Is this good enough?
 	ExactValue_Type,
 
 	ExactValue_Count,
@@ -37,6 +38,7 @@ struct ExactValue {
 		i64           value_pointer;
 		Complex128    value_complex;
 		AstNode *     value_compound;
+		AstNode *     value_procedure;
 		Type *        value_type;
 	};
 };
@@ -109,6 +111,12 @@ ExactValue exact_value_type(Type *type) {
 	return result;
 }
 
+ExactValue exact_value_procedure(AstNode *node) {
+	ExactValue result = {ExactValue_Procedure};
+	result.value_procedure = node;
+	return result;
+}
+
 
 ExactValue exact_value_integer_from_string(String string) {
 	return exact_value_u128(u128_from_string(string));

+ 66 - 30
src/ir.cpp

@@ -20,10 +20,12 @@ struct irModule {
 	// String triple;
 
 	PtrSet<Entity *>      min_dep_set;
-	Map<irValue *>        values;        // Key: Entity *
-	Map<irValue *>        members;       // Key: String
-	Map<String>           entity_names;  // Key: Entity * of the typename
-	Map<irDebugInfo *>    debug_info;    // Key: Unique pointer
+	Map<irValue *>        values;              // Key: Entity *
+	Map<irValue *>        members;             // Key: String
+	Map<String>           entity_names;        // Key: Entity * of the typename
+	Map<irDebugInfo *>    debug_info;          // Key: Unique pointer
+	Map<irValue *>        anonymous_proc_lits; // Key: AstNode *
+
 	i32                   global_string_index;
 	i32                   global_array_index; // For ConstantSlice
 	i32                   global_generated_index;
@@ -3720,6 +3722,38 @@ void ir_pop_target_list(irProcedure *proc) {
 }
 
 
+
+irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, AstNode *expr, irProcedure *proc = nullptr) {
+	ast_node(pl, ProcLit, expr);
+
+	// NOTE(bill): Generate a new name
+	// parent$count
+	isize name_len = prefix_name.len + 1 + 8 + 1;
+	u8 *name_text = gb_alloc_array(m->allocator, u8, name_len);
+	i32 name_id = cast(i32)m->anonymous_proc_lits.entries.count;
+
+	name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$anon-%d", LIT(prefix_name), name_id);
+	String name = make_string(name_text, name_len-1);
+
+	Type *type = type_of_expr(m->info, expr);
+	irValue *value = ir_value_procedure(m->allocator,
+	                                    m, nullptr, type, pl->type, pl->body, name);
+
+	value->Proc.tags = pl->tags;
+	value->Proc.parent = proc;
+
+	array_add(&m->procs_to_generate, value);
+	if (proc != nullptr) {
+		array_add(&proc->children, &value->Proc);
+	} else {
+		map_set(&m->members, hash_string(name), value);
+	}
+
+	map_set(&m->anonymous_proc_lits, hash_pointer(expr), value);
+
+	return value;
+}
+
 void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
 	if (e->type == nullptr) return;
 
@@ -3759,13 +3793,29 @@ void ir_gen_global_type_name(irModule *m, Entity *e, String name) {
 	}
 	#endif
 
+	// if (bt->kind == Type_Struct) {
+	// 	Scope *s = bt->Struct.scope;
+	// 	if (s != nullptr) {
+	// 		for_array(i, s->elements.entries) {
+	// 			Entity *e = s->elements.entries[i].value;
+	// 			if (e->kind == Entity_TypeName) {
+	// 				ir_mangle_add_sub_type_name(m, e, name);
+	// 			}
+	// 		}
+	// 	}
+	// }
+
 	if (bt->kind == Type_Struct) {
-		Scope *s = bt->Struct.scope;
-		if (s != nullptr) {
-			for_array(i, s->elements.entries) {
-				Entity *e = s->elements.entries[i].value;
-				if (e->kind == Entity_TypeName) {
-					ir_mangle_add_sub_type_name(m, e, name);
+		if (bt->Struct.has_proc_default_values) {
+			for_array(i, bt->Struct.fields) {
+				Entity *f = bt->Struct.fields[i];
+				if (f->kind == Entity_Variable) {
+					if (f->Variable.default_value.kind == ExactValue_Procedure) {
+						AstNode *expr = f->Variable.default_value.value_procedure;
+						GB_ASSERT(expr != nullptr);
+						GB_ASSERT(expr->kind == AstNode_ProcLit);
+						ir_gen_anonymous_proc_lit(m, e->token.string, expr);
+					}
 				}
 			}
 		}
@@ -4563,7 +4613,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 	return nullptr;
 }
 
-
 irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	expr = unparen_expr(expr);
 
@@ -4832,24 +4881,7 @@ irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
 	case_end;
 
 	case_ast_node(pl, ProcLit, expr);
-		// NOTE(bill): Generate a new name
-		// parent$count
-		isize name_len = proc->name.len + 1 + 8 + 1;
-		u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
-		name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(proc->name), cast(i32)proc->children.count);
-		String name = make_string(name_text, name_len-1);
-
-		Type *type = type_of_expr(proc->module->info, expr);
-		irValue *value = ir_value_procedure(proc->module->allocator,
-		                                           proc->module, nullptr, type, pl->type, pl->body, name);
-
-		value->Proc.tags = pl->tags;
-		value->Proc.parent = proc;
-
-		array_add(&proc->children, &value->Proc);
-		array_add(&proc->module->procs_to_generate, value);
-
-		return value;
+		return ir_gen_anonymous_proc_lit(proc->module, proc->name, expr, proc);
 	case_end;
 
 
@@ -7424,6 +7456,7 @@ void ir_init_module(irModule *m, Checker *c) {
 	map_init(&m->members,                 heap_allocator());
 	map_init(&m->debug_info,              heap_allocator());
 	map_init(&m->entity_names,            heap_allocator());
+	map_init(&m->anonymous_proc_lits,     heap_allocator());
 	array_init(&m->procs,                 heap_allocator());
 	array_init(&m->procs_to_generate,     heap_allocator());
 	array_init(&m->foreign_library_paths, heap_allocator());
@@ -7532,6 +7565,7 @@ void ir_destroy_module(irModule *m) {
 	map_destroy(&m->values);
 	map_destroy(&m->members);
 	map_destroy(&m->entity_names);
+	map_destroy(&m->anonymous_proc_lits);
 	map_destroy(&m->debug_info);
 	map_destroy(&m->const_strings);
 	array_free(&m->procs);
@@ -8535,7 +8569,9 @@ void ir_gen_tree(irGen *s) {
 
 
 	for_array(i, m->procs_to_generate) {
-		ir_build_proc(m->procs_to_generate[i], m->procs_to_generate[i]->Proc.parent);
+		irValue *p = m->procs_to_generate[i];
+		gb_printf_err("%.*s\n", LIT(p->Proc.name));
+		ir_build_proc(p, p->Proc.parent);
 	}
 
 	// Number debug info

+ 95 - 42
src/ir_print.cpp

@@ -341,7 +341,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 			}
 			return;
 		}
-	} break;
+		break;
+	}
 
 
 	case Type_Named:
@@ -357,7 +358,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 				ir_print_type(f, m, base_type(t));
 				// GB_ASSERT_MSG(found != nullptr, "%.*s %p", LIT(t->Named.name), t->Named.type_name);
 			}
-		} break;
+			break;
+		}
 		default:
 			ir_print_type(f, m, base_type(t));
 			break;
@@ -389,13 +391,15 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
 		generate_map_internal_types(m->allocator, t);
 		GB_ASSERT(t->Map.generated_struct_type != nullptr);
 		ir_print_type(f, m, t->Map.generated_struct_type);
-	} break;
+		break;
+	}
 
 	case Type_BitField: {
 		i64 align = type_align_of(heap_allocator(), t);
 		i64 size  = type_size_of(heap_allocator(),  t);
 		ir_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align, size);
-	} break;
+		break;
+	}
 	}
 }
 
@@ -455,7 +459,8 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ir_print_type(f, m, t_int);
 			ir_fprintf(f, " %lld}", cast(i64)str.len);
 		}
-	} break;
+		break;
+	}
 	case ExactValue_Integer: {
 		if (is_type_pointer(type)) {
 			if (i128_eq(value.value_integer, I128_ZERO)) {
@@ -472,7 +477,8 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 		} else {
 			ir_write_i128(f, value.value_integer);
 		}
-	} break;
+		break;
+	}
 	case ExactValue_Float: {
 		GB_ASSERT_MSG(is_type_float(type), "%s", type_to_string(type));
 		type = core_type(type);
@@ -501,7 +507,8 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ir_fprintf(f, "0x%016llx", u);
 			break;
 		}
-	} break;
+		break;
+	}
 
 	case ExactValue_Complex: {
 		type = core_type(type);
@@ -514,7 +521,8 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 		ir_write_string(f, str_lit(", ")); ir_print_type(f, m, ft); ir_write_byte(f, ' ');
 		ir_print_exact_value(f, m, exact_value_float(value.value_complex.imag), ft);
 		ir_write_byte(f, '}');
-	} break;
+		break;
+	}
 
 	case ExactValue_Pointer:
 		if (value.value_pointer == 0) {
@@ -689,7 +697,19 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			ir_write_string(f, "zeroinitializer");
 		}
 
-	} break;
+		break;
+	}
+
+	case ExactValue_Procedure: {
+		AstNode *expr = value.value_procedure;
+		GB_ASSERT(expr != nullptr);
+		GB_ASSERT(expr->kind == AstNode_ProcLit);
+		irValue **found = map_get(&m->anonymous_proc_lits, hash_pointer(expr));
+		GB_ASSERT(found != nullptr);
+		irValue *val = *found;
+		ir_print_value(f, m, val, type);
+		break;
+	}
 
 	default: {
 		bool has_defaults = ir_type_has_default_values(type);
@@ -745,7 +765,8 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
 			}
 		}
 		// GB_PANIC("Invalid ExactValue: %d", value.kind);
-	} break;
+		break;
+	}
 	}
 }
 
@@ -808,7 +829,8 @@ void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hin
 			ir_print_type(f, m, t_int);
 			ir_fprintf(f, " %lld}", cs->count);
 		}
-	} break;
+		break;
+	}
 
 	case irValue_Nil:
 		ir_write_string(f, "zeroinitializer");
@@ -830,7 +852,8 @@ void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hin
 			in_global_scope = scope->is_global || scope->is_init;
 		}
 		ir_print_encoded_global(f, ir_get_global_name(m, value), in_global_scope);
-	} break;
+		break;
+	}
 	case irValue_Param:
 		ir_print_encoded_local(f, value->Param.entity->token.string);
 		break;
@@ -864,13 +887,15 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 	default: {
 		GB_PANIC("<unknown instr> %d\n", instr->kind);
 		ir_fprintf(f, "; <unknown instr> %d\n", instr->kind);
-	} break;
+		break;
+	}
 
 	case irInstr_StartupRuntime: {
 		ir_write_string(f, "call void ");
 		ir_print_encoded_global(f, str_lit(IR_STARTUP_RUNTIME_PROC_NAME), false);
 		ir_write_string(f, "()\n");
-	} break;
+		break;
+	}
 
 	case irInstr_Comment:
 		ir_write_string(f, "; ");
@@ -887,7 +912,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_fprintf(f, "%%%d = alloca ", value->index);
 		ir_print_type(f, m, type);
 		ir_fprintf(f, ", align %lld\n", align);
-	} break;
+		break;
+	}
 
 	case irInstr_ZeroInit: {
 		Type *type = type_deref(ir_type(instr->ZeroInit.address));
@@ -898,7 +924,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, str_lit(", "));
 		ir_print_type(f, m, type);
 		ir_fprintf(f, "* %%%d\n", instr->ZeroInit.address->index);
-	} break;
+		break;
+	}
 
 	case irInstr_Store: {
 		Type *type = type_deref(ir_type(instr->Store.address));
@@ -911,7 +938,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, "* ");
 		ir_print_value(f, m, instr->Store.address, type);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_Load: {
 		Type *type = instr->Load.type;
@@ -922,7 +950,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, "* ");
 		ir_print_value(f, m, instr->Load.address, type);
 		ir_fprintf(f, ", align %lld\n", type_align_of(m->allocator, type));
-	} break;
+		break;
+	}
 
 	case irInstr_ArrayElementPtr: {
 		Type *et = ir_type(instr->ArrayElementPtr.address);
@@ -947,7 +976,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_byte(f, ' ');
 		ir_print_value(f, m, index, t);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_StructElementPtr: {
 		Type *et = ir_type(instr->StructElementPtr.address);
@@ -973,7 +1003,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_print_type(f, m, t_i32);
 		ir_fprintf(f, " %d", index);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_PtrOffset: {
 		Type *pt = ir_type(instr->PtrOffset.address);
@@ -991,7 +1022,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_byte(f, ' ');
 		ir_print_value(f, m, offset, t);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_Phi: {
 		ir_fprintf(f, "%%%d = phi ", value->index);
@@ -1018,7 +1050,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 			ir_write_string(f, " ]");
 		}
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_StructExtractValue: {
 		Type *et = ir_type(instr->StructExtractValue.address);
@@ -1038,7 +1071,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_byte(f, ' ');
 		ir_print_value(f, m, instr->StructExtractValue.address, et);
 		ir_fprintf(f, ", %d\n", index);
-	} break;
+		break;
+	}
 
 	case irInstr_UnionTagPtr: {
 		Type *et = ir_type(instr->UnionTagPtr.address);
@@ -1062,7 +1096,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 	#endif
 		ir_write_string(f, " ; UnionTagPtr");
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_UnionTagValue: {
 		Type *et = ir_type(instr->UnionTagValue.address);
@@ -1081,13 +1116,15 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 	#endif
 		ir_write_string(f, " ; UnionTagValue");
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_Jump: {;
 		ir_write_string(f, "br label %");
 		ir_print_block_name(f, instr->Jump.block);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_If: {;
 		ir_write_string(f, "br ");
@@ -1098,7 +1135,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, "label %");   ir_print_block_name(f, instr->If.true_block);
 		ir_write_string(f, ", label %"); ir_print_block_name(f, instr->If.false_block);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_Return: {
 		irInstrReturn *ret = &instr->Return;
@@ -1114,7 +1152,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 
 		ir_write_byte(f, '\n');
 
-	} break;
+		break;
+	}
 
 	case irInstr_Conv: {
 		irInstrConv *c = &instr->Conv;
@@ -1126,11 +1165,13 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_print_type(f, m, c->to);
 		ir_write_byte(f, '\n');
 
-	} break;
+		break;
+	}
 
 	case irInstr_Unreachable: {
 		ir_fprintf(f, "unreachable\n");
-	} break;
+		break;
+	}
 
 	case irInstr_UnaryOp: {
 		irInstrUnaryOp *uo = &value->Instr.UnaryOp;
@@ -1179,7 +1220,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, str_lit(", "));
 		ir_print_value(f, m, uo->expr, type);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_BinaryOp: {
 		irInstrBinaryOp *bo = &value->Instr.BinaryOp;
@@ -1311,7 +1353,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 				case Token_Quo: ir_write_string(f, "div"); break;
 				case Token_Mod: ir_write_string(f, "rem"); break;
 				}
-			} break;
+				break;
+			}
 			}
 		}
 
@@ -1322,7 +1365,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_string(f, str_lit(", "));
 		ir_print_value(f, m, bo->right, type);
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	case irInstr_Call: {
 		irInstrCall *call = &instr->Call;
@@ -1421,7 +1465,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		}
 		ir_write_string(f, ")\n");
 
-	} break;
+		break;
+	}
 
 	case irInstr_Select: {
 		ir_fprintf(f, "%%%d = select i1 ", value->index);
@@ -1435,7 +1480,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_write_byte(f, ' ');
 		ir_print_value(f, m, instr->Select.false_value, ir_type(instr->Select.false_value));
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 
 	// case irInstr_VectorExtractElement: {
 		// Type *vt = ir_type(instr->VectorExtractElement.vector);
@@ -1450,7 +1496,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		// ir_write_byte(f, ' ');
 		// ir_print_value(f, m, instr->VectorExtractElement.index, it);
 		// ir_write_byte(f, '\n');
-	// } break;
+		// break;
+	// }
 
 	// case irInstr_VectorInsertElement: {
 	// 	irInstrVectorInsertElement *ie = &instr->VectorInsertElement;
@@ -1472,7 +1519,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 	// 	ir_print_value(f, m, ie->index, ir_type(ie->index));
 
 	// 	ir_write_byte(f, '\n');
-	// } break;
+	// break;
+	// }
 
 	// case irInstr_VectorShuffle: {
 	// 	irInstrVectorShuffle *sv = &instr->VectorShuffle;
@@ -1498,7 +1546,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 	// 	}
 	// 	ir_fprintf(f, ">");
 	// 	ir_write_byte(f, '\n');
-	// } break;
+	//	break;
+	// }
 
 	#if 0
 	case irInstr_BoundsCheck: {
@@ -1529,7 +1578,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_print_value(f, m, bc->len, t_int);
 
 		ir_fprintf(f, ")\n");
-	} break;
+		break;
+	}
 
 	case irInstr_SliceBoundsCheck: {
 		irInstrSliceBoundsCheck *bc = &instr->SliceBoundsCheck;
@@ -1571,7 +1621,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		}
 
 		ir_fprintf(f, ")\n");
-	} break;
+		break;
+	}
 	#endif
 
 	case irInstr_DebugDeclare: {
@@ -1596,7 +1647,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, di->id);
 
 		ir_write_byte(f, '\n');
-	} break;
+		break;
+	}
 	}
 }
 
@@ -1925,7 +1977,8 @@ void print_llvm_ir(irGen *ir) {
 				            ")",
 				            file->id);
 
-			} break;
+				break;
+			}
 			case irDebugInfo_File:
 				ir_fprintf(f, "!DIFile(filename: \"");
 				ir_print_escape_string(f, di->File.filename, false);

+ 1 - 0
src/types.cpp

@@ -82,6 +82,7 @@ struct TypeStruct {
 	bool       is_raw_union;
 	bool       is_polymorphic;
 	bool       is_poly_specialized;
+	bool       has_proc_default_values;
 	Type *     polymorphic_params; // Type_Tuple
 	Type *     polymorphic_parent;