Browse Source

Fix (Crude) cyclic type checking for arrays and vectors

Ginger Bill 8 years ago
parent
commit
8ec9811d7a
3 changed files with 100 additions and 33 deletions
  1. 11 0
      code/demo.odin
  2. 2 1
      src/checker/checker.c
  3. 87 32
      src/checker/types.c

+ 11 - 0
code/demo.odin

@@ -1,6 +1,17 @@
 // #import "game.odin";
 // #import "game.odin";
 #import "fmt.odin";
 #import "fmt.odin";
 
 
+A :: type struct {
+	b: B;
+};
+B :: type struct {
+	c: C;
+};
+C :: type struct {
+	a: A;
+};
+
+
 main :: proc() {
 main :: proc() {
 	fmt.println(123);
 	fmt.println(123);
 }
 }

+ 2 - 1
src/checker/checker.c

@@ -1465,11 +1465,12 @@ void check_parsed_files(Checker *c) {
 		}
 		}
 	}
 	}
 
 
+	// NOTE(bill): Check for illegal cyclic type declarations
 	for_array(i, c->info.definitions.entries) {
 	for_array(i, c->info.definitions.entries) {
 		Entity *e = c->info.definitions.entries.e[i].value;
 		Entity *e = c->info.definitions.entries.e[i].value;
 		if (e->kind == Entity_TypeName) {
 		if (e->kind == Entity_TypeName) {
+			// i64 size  = type_size_of(c->sizes, c->allocator, e->type);
 			i64 align = type_align_of(c->sizes, c->allocator, e->type);
 			i64 align = type_align_of(c->sizes, c->allocator, e->type);
-			GB_ASSERT(align > 0);
 		}
 		}
 	}
 	}
 }
 }

+ 87 - 32
src/checker/types.c

@@ -1093,11 +1093,15 @@ void type_path_pop(TypePath *tp) {
 }
 }
 
 
 
 
+#define FAILURE_SIZE      0
+#define FAILURE_ALIGNMENT 0
+
 
 
 i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
 i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
 i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
 i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
 i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
 i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
 
 
+i64 type_size_of_internal (BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path);
 i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path);
 i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path);
 
 
 i64 align_formula(i64 size, i64 align) {
 i64 align_formula(i64 size, i64 align) {
@@ -1108,7 +1112,14 @@ i64 align_formula(i64 size, i64 align) {
 	return size;
 	return size;
 }
 }
 
 
-
+i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
+	i64 align;
+	TypePath path = {0};
+	type_path_init(&path);
+	align = type_size_of_internal(s, allocator, t, &path);
+	type_path_free(&path);
+	return align;
+}
 
 
 i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 	i64 align;
 	i64 align;
@@ -1119,16 +1130,29 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 	return align;
 	return align;
 }
 }
 
 
-#define FAILURE_ALIGNMENT (-1)
 
 
 i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path) {
 i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path) {
 	t = base_type(t);
 	t = base_type(t);
 
 
 	switch (t->kind) {
 	switch (t->kind) {
-	case Type_Array:
-		return type_align_of_internal(s, allocator, t->Array.elem, path);
+	case Type_Array: {
+		Type *elem = t->Array.elem;
+		type_path_push(path, elem);
+		if (path->failure) {
+			return FAILURE_ALIGNMENT;
+		}
+		i64 align = type_align_of_internal(s, allocator, t->Array.elem, path);
+		type_path_pop(path);
+		return align;
+	}
 	case Type_Vector: {
 	case Type_Vector: {
-		i64 size = type_size_of(s, allocator, t->Vector.elem);
+		Type *elem = t->Vector.elem;
+		type_path_push(path, elem);
+		if (path->failure) {
+			return FAILURE_ALIGNMENT;
+		}
+		i64 size = type_size_of_internal(s, allocator, t->Vector.elem, path);
+		type_path_pop(path);
 		i64 count = gb_max(prev_pow2(t->Vector.count), 1);
 		i64 count = gb_max(prev_pow2(t->Vector.count), 1);
 		i64 total = size * count;
 		i64 total = size * count;
 		return gb_clamp(total, 1, s.max_align);
 		return gb_clamp(total, 1, s.max_align);
@@ -1145,8 +1169,16 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
 		return max;
 		return max;
 	} break;
 	} break;
 
 
-	case Type_Maybe:
-		return gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path));
+	case Type_Maybe: {
+		Type *elem = t->Maybe.elem;
+		type_path_push(path, elem);
+		if (path->failure) {
+			return FAILURE_ALIGNMENT;
+		}
+		i64 align = gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path));
+		type_path_pop(path);
+		return align;
+	}
 
 
 	case Type_Record: {
 	case Type_Record: {
 		switch (t->Record.kind) {
 		switch (t->Record.kind) {
@@ -1221,7 +1253,7 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
 	// return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
 	// return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
 	// NOTE(bill): Things that are bigger than s.word_size, are actually comprised of smaller types
 	// NOTE(bill): Things that are bigger than s.word_size, are actually comprised of smaller types
 	// TODO(bill): Is this correct for 128-bit types (integers)?
 	// TODO(bill): Is this correct for 128-bit types (integers)?
-	return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.word_size);
+	return gb_clamp(next_pow2(type_size_of_internal(s, allocator, t, path)), 1, s.word_size);
 }
 }
 
 
 i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, bool is_packed) {
 i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, bool is_packed) {
@@ -1264,7 +1296,7 @@ bool type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 	return false;
 	return false;
 }
 }
 
 
-i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
+i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path) {
 	t = base_type(t);
 	t = base_type(t);
 	switch (t->kind) {
 	switch (t->kind) {
 	case Type_Basic: {
 	case Type_Basic: {
@@ -1284,29 +1316,38 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 	} break;
 	} break;
 
 
 	case Type_Array: {
 	case Type_Array: {
-		i64 count = t->Array.count;
+		i64 count, align, size, alignment;
+		count = t->Array.count;
 		if (count == 0) {
 		if (count == 0) {
 			return 0;
 			return 0;
 		}
 		}
-		i64 align = type_align_of(s, allocator, t->Array.elem);
-		i64 size  = type_size_of(s,  allocator, t->Array.elem);
-		i64 alignment = align_formula(size, align);
+		align = type_align_of_internal(s, allocator, t->Array.elem, path);
+		if (path->failure) {
+			return FAILURE_SIZE;
+		}
+		size  = type_size_of_internal(s,  allocator, t->Array.elem, path);
+		alignment = align_formula(size, align);
 		return alignment*(count-1) + size;
 		return alignment*(count-1) + size;
 	} break;
 	} break;
 
 
 	case Type_Vector: {
 	case Type_Vector: {
-		i64 count = t->Vector.count;
+		i64 count, bit_size, total_size_in_bits, total_size;
+		count = t->Vector.count;
 		if (count == 0) {
 		if (count == 0) {
 			return 0;
 			return 0;
 		}
 		}
-		// i64 align = type_align_of(s, allocator, t->Vector.elem);
-		i64 bit_size = 8*type_size_of(s,  allocator, t->Vector.elem);
+		type_path_push(path, t->Vector.elem);
+		if (path->failure) {
+			return FAILURE_SIZE;
+		}
+		bit_size = 8*type_size_of_internal(s, allocator, t->Vector.elem, path);
+		type_path_pop(path);
 		if (is_type_boolean(t->Vector.elem)) {
 		if (is_type_boolean(t->Vector.elem)) {
 			bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
 			bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
 			              // Silly LLVM spec
 			              // Silly LLVM spec
 		}
 		}
-		i64 total_size_in_bits = bit_size * count;
-		i64 total_size = (total_size_in_bits+7)/8;
+		total_size_in_bits = bit_size * count;
+		total_size = (total_size_in_bits+7)/8;
 		return total_size;
 		return total_size;
 	} break;
 	} break;
 
 
@@ -1315,21 +1356,26 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 		return 3 * s.word_size;
 		return 3 * s.word_size;
 
 
 	case Type_Maybe: { // value + bool
 	case Type_Maybe: { // value + bool
+		i64 align, size;
 		Type *elem = t->Maybe.elem;
 		Type *elem = t->Maybe.elem;
-		i64 align = type_align_of(s, allocator, elem);
-		i64 size = align_formula(type_size_of(s, allocator, elem), align);
-		size += type_size_of(s, allocator, t_bool);
+		align = type_align_of_internal(s, allocator, elem, path);
+		if (path->failure) {
+			return FAILURE_SIZE;
+		}
+		size = align_formula(type_size_of_internal(s, allocator, elem, path), align);
+		size += type_size_of_internal(s, allocator, t_bool, path);
 		return align_formula(size, align);
 		return align_formula(size, align);
 	}
 	}
 
 
 	case Type_Tuple: {
 	case Type_Tuple: {
-		i64 count = t->Tuple.variable_count;
+		i64 count, align, size;
+		count = t->Tuple.variable_count;
 		if (count == 0) {
 		if (count == 0) {
 			return 0;
 			return 0;
 		}
 		}
-		i64 align = type_align_of(s, allocator, t);
+		align = type_align_of_internal(s, allocator, t, path);
 		type_set_offsets(s, allocator, t);
 		type_set_offsets(s, allocator, t);
-		i64 size = t->Tuple.offsets[count-1] + type_size_of(s, allocator, t->Tuple.variables[count-1]->type);
+		size = t->Tuple.offsets[count-1] + type_size_of_internal(s, allocator, t->Tuple.variables[count-1]->type, path);
 		return align_formula(size, align);
 		return align_formula(size, align);
 	} break;
 	} break;
 
 
@@ -1340,35 +1386,44 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 			if (count == 0) {
 			if (count == 0) {
 				return 0;
 				return 0;
 			}
 			}
-			i64 align = type_align_of(s, allocator, t);
+			i64 align = type_align_of_internal(s, allocator, t, path);
+			if (path->failure) {
+				return FAILURE_SIZE;
+			}
 			type_set_offsets(s, allocator, t);
 			type_set_offsets(s, allocator, t);
-			i64 size = t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type);
+			i64 size = t->Record.struct_offsets[count-1] + type_size_of_internal(s, allocator, t->Record.fields[count-1]->type, path);
 			return align_formula(size, align);
 			return align_formula(size, align);
 		} break;
 		} break;
 
 
 		case TypeRecord_Union: {
 		case TypeRecord_Union: {
 			i64 count = t->Record.field_count;
 			i64 count = t->Record.field_count;
-			i64 align = type_align_of(s, allocator, t);
+			i64 align = type_align_of_internal(s, allocator, t, path);
+			if (path->failure) {
+				return FAILURE_SIZE;
+			}
 			i64 max = 0;
 			i64 max = 0;
 			// NOTE(bill): Zeroth field is invalid
 			// NOTE(bill): Zeroth field is invalid
 			for (isize i = 1; i < count; i++) {
 			for (isize i = 1; i < count; i++) {
-				i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
+				i64 size = type_size_of_internal(s, allocator, t->Record.fields[i]->type, path);
 				if (max < size) {
 				if (max < size) {
 					max = size;
 					max = size;
 				}
 				}
 			}
 			}
 			// NOTE(bill): Align to int
 			// NOTE(bill): Align to int
 			isize size =  align_formula(max, s.word_size);
 			isize size =  align_formula(max, s.word_size);
-			size += type_size_of(s, allocator, t_int);
+			size += type_size_of_internal(s, allocator, t_int, path);
 			return align_formula(size, align);
 			return align_formula(size, align);
 		} break;
 		} break;
 
 
 		case TypeRecord_RawUnion: {
 		case TypeRecord_RawUnion: {
 			i64 count = t->Record.field_count;
 			i64 count = t->Record.field_count;
-			i64 align = type_align_of(s, allocator, t);
+			i64 align = type_align_of_internal(s, allocator, t, path);
+			if (path->failure) {
+				return FAILURE_SIZE;
+			}
 			i64 max = 0;
 			i64 max = 0;
 			for (isize i = 0; i < count; i++) {
 			for (isize i = 0; i < count; i++) {
-				i64 size = type_size_of(s, allocator, t->Record.fields[i]->type);
+				i64 size = type_size_of_internal(s, allocator, t->Record.fields[i]->type, path);
 				if (max < size) {
 				if (max < size) {
 					max = size;
 					max = size;
 				}
 				}
@@ -1378,7 +1433,7 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 		} break;
 		} break;
 
 
 		case TypeRecord_Enum: {
 		case TypeRecord_Enum: {
-			return type_size_of(s, allocator, t->Record.enum_base);
+			return type_size_of_internal(s, allocator, t->Record.enum_base, path);
 		} break;
 		} break;
 		}
 		}
 	} break;
 	} break;