From 8ec9811d7a552e96600286a58b5b5303b79f88ed Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 4 Dec 2016 23:41:21 +0000 Subject: [PATCH] Fix (Crude) cyclic type checking for arrays and vectors --- code/demo.odin | 11 ++++ src/checker/checker.c | 3 +- src/checker/types.c | 119 ++++++++++++++++++++++++++++++------------ 3 files changed, 100 insertions(+), 33 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index d01db00ac..4198c1468 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,6 +1,17 @@ // #import "game.odin"; #import "fmt.odin"; +A :: type struct { + b: B; +}; +B :: type struct { + c: C; +}; +C :: type struct { + a: A; +}; + + main :: proc() { fmt.println(123); } diff --git a/src/checker/checker.c b/src/checker/checker.c index cf95c146b..06caab6c4 100644 --- a/src/checker/checker.c +++ b/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) { Entity *e = c->info.definitions.entries.e[i].value; 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); - GB_ASSERT(align > 0); } } } diff --git a/src/checker/types.c b/src/checker/types.c index ee4a65262..91847b477 100644 --- a/src/checker/types.c +++ b/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_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t); 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 align_formula(i64 size, i64 align) { @@ -1108,7 +1112,14 @@ i64 align_formula(i64 size, i64 align) { 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 align; @@ -1119,16 +1130,29 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { return align; } -#define FAILURE_ALIGNMENT (-1) i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path) { t = base_type(t); 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: { - 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 total = size * count; 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; } 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: { 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); // 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)? - 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) { @@ -1264,7 +1296,7 @@ bool type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) { 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); switch (t->kind) { case Type_Basic: { @@ -1284,29 +1316,38 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } break; case Type_Array: { - i64 count = t->Array.count; + i64 count, align, size, alignment; + count = t->Array.count; if (count == 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; } break; 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) { 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)) { bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1` // 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; } break; @@ -1315,21 +1356,26 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { return 3 * s.word_size; case Type_Maybe: { // value + bool + i64 align, size; 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); } case Type_Tuple: { - i64 count = t->Tuple.variable_count; + i64 count, align, size; + count = t->Tuple.variable_count; if (count == 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); - 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); } break; @@ -1340,35 +1386,44 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { if (count == 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); - 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); } break; case TypeRecord_Union: { 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; // NOTE(bill): Zeroth field is invalid 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) { max = size; } } // NOTE(bill): Align to int 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); } break; case TypeRecord_RawUnion: { 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; 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) { max = size; } @@ -1378,7 +1433,7 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } break; 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;