mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Fix (Crude) cyclic type checking for arrays and vectors
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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:
|
case Type_Array: {
|
||||||
return type_align_of_internal(s, allocator, t->Array.elem, path);
|
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:
|
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));
|
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);
|
align = type_align_of_internal(s, allocator, t->Array.elem, path);
|
||||||
i64 size = type_size_of(s, allocator, t->Array.elem);
|
if (path->failure) {
|
||||||
i64 alignment = align_formula(size, align);
|
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);
|
type_path_push(path, t->Vector.elem);
|
||||||
i64 bit_size = 8*type_size_of(s, allocator, 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;
|
total_size_in_bits = bit_size * count;
|
||||||
i64 total_size = (total_size_in_bits+7)/8;
|
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);
|
align = type_align_of_internal(s, allocator, elem, path);
|
||||||
i64 size = align_formula(type_size_of(s, allocator, elem), align);
|
if (path->failure) {
|
||||||
size += type_size_of(s, allocator, t_bool);
|
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user