Bladeren bron

Fix bug with union literal checking crashing the compiler

Ginger Bill 8 jaren geleden
bovenliggende
commit
95692fda52
4 gewijzigde bestanden met toevoegingen van 25 en 14 verwijderingen
  1. 4 3
      src/check_expr.c
  2. 6 5
      src/ir.c
  3. 2 2
      src/tokenizer.c
  4. 13 4
      src/types.c

+ 4 - 3
src/check_expr.c

@@ -599,9 +599,10 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
 		map_entity_set(&entity_map, hash_string(name), f);
 	}
 
-	union_type->Record.fields      = fields;
-	union_type->Record.field_count = field_count;
-	union_type->Record.are_offsets_set = false;
+	union_type->Record.fields              = fields;
+	union_type->Record.fields_in_src_order = fields;
+	union_type->Record.field_count         = field_count;
+	union_type->Record.are_offsets_set     = false;
 
 
 	for_array(i, ut->variants) {

+ 6 - 5
src/ir.c

@@ -2525,14 +2525,14 @@ irValue *ir_string_len(irProcedure *proc, irValue *string) {
 }
 
 
-void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *count, irValue *capacity) {
+void ir_fill_slice(irProcedure *proc, irValue *slice_ptr, irValue *data, irValue *len, irValue *cap) {
 	Type *t = ir_type(slice_ptr);
 	GB_ASSERT(is_type_pointer(t));
 	t = type_deref(t);
 	GB_ASSERT(is_type_slice(t));
 	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 0), data);
-	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), count);
-	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), capacity);
+	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 1), len);
+	ir_emit_store(proc, ir_emit_struct_ep(proc, slice_ptr, 2), cap);
 }
 
 
@@ -2771,7 +2771,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
 				ir_emit_comment(proc, str_lit("union - child to parent"));
 				gbAllocator a = proc->module->allocator;
 				irValue *parent = ir_add_local_generated(proc, t);
-				irValue *underlying = ir_emit_conv(proc, parent, make_type_pointer(a, src_type));
+				irValue *underlying = ir_emit_conv(proc, parent, make_type_pointer(a, f->type));
 				ir_emit_store(proc, underlying, value);
 
 				irValue *tag_ptr = ir_emit_union_tag_ptr(proc, parent);
@@ -5073,7 +5073,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 
 					if (elem->kind == AstNode_FieldValue) {
 						ast_node(fv, FieldValue, elem);
-						Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
+						String name = fv->field->Ident.string;
+						Selection sel = lookup_field(proc->module->allocator, bt, name, false);
 						index = sel.index.e[0];
 						elem = fv->value;
 					} else {

+ 2 - 2
src/tokenizer.c

@@ -170,8 +170,8 @@ Token make_token_ident(String s) {
 
 typedef struct ErrorCollector {
 	TokenPos prev;
-	i64 count;
-	i64 warning_count;
+	i64     count;
+	i64     warning_count;
 	gbMutex mutex;
 } ErrorCollector;
 

+ 13 - 4
src/types.c

@@ -1718,10 +1718,10 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 			if (t->Record.field_count > 0) {
 				Type *field_type = t->Record.fields[0]->type;
 				type_path_push(path, field_type);
+				i64 align = type_align_of_internal(allocator, field_type, path);
 				if (path->failure) {
 					return FAILURE_ALIGNMENT;
 				}
-				i64 align = type_align_of_internal(allocator, field_type, path);
 				type_path_pop(path);
 				if (max < align) {
 					max = align;
@@ -1943,12 +1943,21 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 			if (path->failure) {
 				return FAILURE_SIZE;
 			}
-			// NOTE(bill): Zeroth field is invalid
-			type_set_offsets(allocator, t);
 
 			i64 max = 0;
 			isize field_count = t->Record.field_count;
 			isize variant_count = t->Record.variant_count;
+
+			// Check for recursive types
+			for (isize i = 0; i < field_count; i++) {
+				i64 size = type_size_of_internal(allocator, t->Record.fields[i]->type, path);
+				if (path->failure) {
+					return FAILURE_SIZE;
+				}
+			}
+			// NOTE(bill): Zeroth field is invalid
+			type_set_offsets(allocator, t);
+
 			if (field_count > 0) {
 				Type *end_type = t->Record.fields[field_count-1]->type;
 				i64 end_offset = t->Record.offsets[field_count-1];
@@ -1996,7 +2005,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
 
 i64 type_offset_of(gbAllocator allocator, Type *t, i32 index) {
 	t = base_type(t);
-	if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
+	if (t->kind == Type_Record && (t->Record.kind == TypeRecord_Struct || t->Record.kind == TypeRecord_Union)) {
 		type_set_offsets(allocator, t);
 		if (gb_is_between(index, 0, t->Record.field_count-1)) {
 			return t->Record.offsets[index];