mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
(Crude) Cyclic Type Checking
This commit is contained in:
@@ -16,7 +16,7 @@ if %release_mode% EQU 0 ( rem Debug
|
|||||||
)
|
)
|
||||||
|
|
||||||
set compiler_warnings= ^
|
set compiler_warnings= ^
|
||||||
-we4002 -we4013 -we4024 -we4047 -we4133 -we4706 ^
|
-we4002 -we4013 -we4020 -we4024 -we4029 -we4031 -we4047 -we4133 -we4706 ^
|
||||||
-wd4100 -wd4101 -wd4127 -wd4189 ^
|
-wd4100 -wd4101 -wd4127 -wd4189 ^
|
||||||
-wd4201 -wd4204 -wd4244 ^
|
-wd4201 -wd4204 -wd4244 ^
|
||||||
-wd4306 ^
|
-wd4306 ^
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// #import "game.odin";
|
// #import "game.odin";
|
||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
|
|
||||||
x := type_info(int);
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println(123);
|
fmt.println(123);
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-25
@@ -269,33 +269,9 @@ typedef struct Checker {
|
|||||||
bool done_preload;
|
bool done_preload;
|
||||||
} Checker;
|
} Checker;
|
||||||
|
|
||||||
typedef struct CycleChecker {
|
|
||||||
Array(Entity *) path; // Entity_TypeName
|
|
||||||
} CycleChecker;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CycleChecker *cycle_checker_add(CycleChecker *cc, Entity *e) {
|
|
||||||
if (cc == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (cc->path.e == NULL) {
|
|
||||||
array_init(&cc->path, heap_allocator());
|
|
||||||
}
|
|
||||||
if (e != NULL && e->kind == Entity_TypeName) {
|
|
||||||
array_add(&cc->path, e);
|
|
||||||
}
|
|
||||||
return cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cycle_checker_destroy(CycleChecker *cc) {
|
|
||||||
if (cc != NULL && cc->path.e != NULL) {
|
|
||||||
array_free(&cc->path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_declaration_info(DeclInfo *d, Scope *scope) {
|
void init_declaration_info(DeclInfo *d, Scope *scope) {
|
||||||
d->scope = scope;
|
d->scope = scope;
|
||||||
map_bool_init(&d->deps, heap_allocator());
|
map_bool_init(&d->deps, heap_allocator());
|
||||||
@@ -1095,7 +1071,7 @@ void check_all_global_entities(Checker *c) {
|
|||||||
|
|
||||||
Scope *prev_scope = c->context.scope;
|
Scope *prev_scope = c->context.scope;
|
||||||
c->context.scope = d->scope;
|
c->context.scope = d->scope;
|
||||||
check_entity_decl(c, e, d, NULL, NULL);
|
check_entity_decl(c, e, d, NULL);
|
||||||
|
|
||||||
|
|
||||||
if (d->scope->is_init && !c->done_preload) {
|
if (d->scope->is_init && !c->done_preload) {
|
||||||
@@ -1488,6 +1464,14 @@ void check_parsed_files(Checker *c) {
|
|||||||
add_type_info_type(c, t);
|
add_type_info_type(c, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_array(i, c->info.definitions.entries) {
|
||||||
|
Entity *e = c->info.definitions.entries.e[i].value;
|
||||||
|
if (e->kind == Entity_TypeName) {
|
||||||
|
i64 align = type_align_of(c->sizes, c->allocator, e->type);
|
||||||
|
GB_ASSERT(align > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+54
-69
@@ -1,10 +1,6 @@
|
|||||||
bool check_is_terminating(AstNode *node);
|
bool check_is_terminating(AstNode *node);
|
||||||
void check_stmt (Checker *c, AstNode *node, u32 flags);
|
void check_stmt (Checker *c, AstNode *node, u32 flags);
|
||||||
void check_stmt_list (Checker *c, AstNodeArray stmts, u32 flags);
|
void check_stmt_list (Checker *c, AstNodeArray stmts, u32 flags);
|
||||||
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker);
|
|
||||||
void check_const_decl (Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr);
|
|
||||||
void check_proc_decl (Checker *c, Entity *e, DeclInfo *d);
|
|
||||||
void check_var_decl (Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr);
|
|
||||||
|
|
||||||
// NOTE(bill): `content_name` is for debugging and error messages
|
// NOTE(bill): `content_name` is for debugging and error messages
|
||||||
Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) {
|
Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) {
|
||||||
@@ -103,56 +99,6 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
|
|
||||||
if (e->type != NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d == NULL) {
|
|
||||||
DeclInfo **found = map_decl_info_get(&c->info.entities, hash_pointer(e));
|
|
||||||
if (found) {
|
|
||||||
d = *found;
|
|
||||||
} else {
|
|
||||||
e->type = t_invalid;
|
|
||||||
set_base_type(named_type, t_invalid);
|
|
||||||
return;
|
|
||||||
// GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (e->kind == Entity_Procedure) {
|
|
||||||
check_proc_decl(c, e, d);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
CheckerContext prev = c->context;
|
|
||||||
c->context.scope = d->scope;
|
|
||||||
c->context.decl = d;
|
|
||||||
|
|
||||||
switch (e->kind) {
|
|
||||||
case Entity_Constant:
|
|
||||||
check_const_decl(c, e, d->type_expr, d->init_expr);
|
|
||||||
break;
|
|
||||||
case Entity_Variable:
|
|
||||||
check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
|
|
||||||
break;
|
|
||||||
case Entity_TypeName:
|
|
||||||
check_type_decl(c, e, d->type_expr, named_type, cycle_checker);
|
|
||||||
break;
|
|
||||||
#if 1
|
|
||||||
case Entity_Procedure:
|
|
||||||
check_proc_decl(c, e, d);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
c->context = prev;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_var_decl_node(Checker *c, AstNode *node) {
|
void check_var_decl_node(Checker *c, AstNode *node) {
|
||||||
ast_node(vd, VarDecl, node);
|
ast_node(vd, VarDecl, node);
|
||||||
isize entity_count = vd->names.count;
|
isize entity_count = vd->names.count;
|
||||||
@@ -192,7 +138,7 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
|||||||
|
|
||||||
Type *init_type = NULL;
|
Type *init_type = NULL;
|
||||||
if (vd->type) {
|
if (vd->type) {
|
||||||
init_type = check_type_extra(c, vd->type, NULL, NULL);
|
init_type = check_type_extra(c, vd->type, NULL);
|
||||||
if (init_type == NULL)
|
if (init_type == NULL)
|
||||||
init_type = t_invalid;
|
init_type = t_invalid;
|
||||||
}
|
}
|
||||||
@@ -292,7 +238,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e
|
|||||||
check_init_constant(c, e, &operand);
|
check_init_constant(c, e, &operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker) {
|
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
||||||
named->Named.type_name = e;
|
named->Named.type_name = e;
|
||||||
@@ -301,19 +247,13 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
|||||||
}
|
}
|
||||||
e->type = named;
|
e->type = named;
|
||||||
|
|
||||||
CycleChecker local_cycle_checker = {0};
|
// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
|
||||||
if (cycle_checker == NULL) {
|
|
||||||
cycle_checker = &local_cycle_checker;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *bt = check_type_extra(c, type_expr, named, cycle_checker_add(cycle_checker, e));
|
Type *bt = check_type_extra(c, type_expr, named);
|
||||||
named->Named.base = bt;
|
named->Named.base = base_type(bt);
|
||||||
named->Named.base = base_type(named->Named.base);
|
|
||||||
if (named->Named.base == t_invalid) {
|
if (named->Named.base == t_invalid) {
|
||||||
// gb_printf("check_type_decl: %s\n", type_to_string(named));
|
// gb_printf("check_type_decl: %s\n", type_to_string(named));
|
||||||
}
|
}
|
||||||
|
|
||||||
cycle_checker_destroy(&local_cycle_checker);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -458,12 +398,14 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
}
|
}
|
||||||
e->flags |= EntityFlag_Visited;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
if (type_expr != NULL)
|
if (type_expr != NULL) {
|
||||||
e->type = check_type_extra(c, type_expr, NULL, NULL);
|
e->type = check_type_extra(c, type_expr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (init_expr == NULL) {
|
if (init_expr == NULL) {
|
||||||
if (type_expr == NULL)
|
if (type_expr == NULL) {
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,8 +417,9 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type_expr != NULL) {
|
if (type_expr != NULL) {
|
||||||
for (isize i = 0; i < entity_count; i++)
|
for (isize i = 0; i < entity_count; i++) {
|
||||||
entities[i]->type = e->type;
|
entities[i]->type = e->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNodeArray inits;
|
AstNodeArray inits;
|
||||||
@@ -485,6 +428,48 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
|
check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||||
|
if (e->type != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d == NULL) {
|
||||||
|
DeclInfo **found = map_decl_info_get(&c->info.entities, hash_pointer(e));
|
||||||
|
if (found) {
|
||||||
|
d = *found;
|
||||||
|
} else {
|
||||||
|
e->type = t_invalid;
|
||||||
|
set_base_type(named_type, t_invalid);
|
||||||
|
return;
|
||||||
|
// GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckerContext prev = c->context;
|
||||||
|
c->context.scope = d->scope;
|
||||||
|
c->context.decl = d;
|
||||||
|
|
||||||
|
switch (e->kind) {
|
||||||
|
case Entity_Constant:
|
||||||
|
check_const_decl(c, e, d->type_expr, d->init_expr);
|
||||||
|
break;
|
||||||
|
case Entity_Variable:
|
||||||
|
check_var_decl(c, e, d->entities, d->entity_count, d->type_expr, d->init_expr);
|
||||||
|
break;
|
||||||
|
case Entity_TypeName:
|
||||||
|
check_type_decl(c, e, d->type_expr, named_type);
|
||||||
|
break;
|
||||||
|
case Entity_Procedure:
|
||||||
|
check_proc_decl(c, e, d);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->context = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
|
||||||
GB_ASSERT(body->kind == AstNode_BlockStmt);
|
GB_ASSERT(body->kind == AstNode_BlockStmt);
|
||||||
|
|
||||||
|
|||||||
+33
-50
@@ -2,20 +2,20 @@ void check_expr (Checker *c, Operand *operand, AstNode *expre
|
|||||||
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
void check_multi_expr (Checker *c, Operand *operand, AstNode *expression);
|
||||||
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
void check_expr_or_type (Checker *c, Operand *operand, AstNode *expression);
|
||||||
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
|
ExprKind check_expr_base (Checker *c, Operand *operand, AstNode *expression, Type *type_hint);
|
||||||
Type * check_type_extra (Checker *c, AstNode *expression, Type *named_type, CycleChecker *cycle_checker);
|
Type * check_type_extra (Checker *c, AstNode *expression, Type *named_type);
|
||||||
Type * check_type (Checker *c, AstNode *expression);
|
Type * check_type (Checker *c, AstNode *expression);
|
||||||
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker);
|
void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, Type *def);
|
||||||
Entity * check_selector (Checker *c, Operand *operand, AstNode *node);
|
Entity * check_selector (Checker *c, Operand *operand, AstNode *node);
|
||||||
void check_not_tuple (Checker *c, Operand *operand);
|
void check_not_tuple (Checker *c, Operand *operand);
|
||||||
bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
||||||
void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level);
|
void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level);
|
||||||
gbString expr_to_string (AstNode *expression);
|
gbString expr_to_string (AstNode *expression);
|
||||||
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type, CycleChecker *cycle_checker);
|
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type);
|
||||||
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
||||||
void update_expr_type (Checker *c, AstNode *e, Type *type, bool final);
|
void update_expr_type (Checker *c, AstNode *e, Type *type, bool final);
|
||||||
|
|
||||||
gb_inline Type *check_type(Checker *c, AstNode *expression) {
|
gb_inline Type *check_type(Checker *c, AstNode *expression) {
|
||||||
return check_type_extra(c, expression, NULL, NULL);
|
return check_type_extra(c, expression, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -225,13 +225,13 @@ void check_scope_decls(Checker *c, AstNodeArray nodes, isize reserve_size, Delay
|
|||||||
for_array(i, delayed_entities) {
|
for_array(i, delayed_entities) {
|
||||||
DelayedEntity delayed = delayed_entities.e[i];
|
DelayedEntity delayed = delayed_entities.e[i];
|
||||||
if (delayed.entity->kind == Entity_TypeName) {
|
if (delayed.entity->kind == Entity_TypeName) {
|
||||||
check_entity_decl(c, delayed.entity, delayed.decl, NULL, NULL);
|
check_entity_decl(c, delayed.entity, delayed.decl, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for_array(i, delayed_entities) {
|
for_array(i, delayed_entities) {
|
||||||
DelayedEntity delayed = delayed_entities.e[i];
|
DelayedEntity delayed = delayed_entities.e[i];
|
||||||
if (delayed.entity->kind == Entity_Constant) {
|
if (delayed.entity->kind == Entity_Constant) {
|
||||||
check_entity_decl(c, delayed.entity, delayed.decl, NULL, NULL);
|
check_entity_decl(c, delayed.entity, delayed.decl, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +460,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e
|
|||||||
void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||||
Entity **fields, isize field_count,
|
Entity **fields, isize field_count,
|
||||||
Entity **other_fields, isize other_field_count,
|
Entity **other_fields, isize other_field_count,
|
||||||
CycleChecker *cycle_checker, String context) {
|
String context) {
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
|
|
||||||
MapEntity entity_map = {0};
|
MapEntity entity_map = {0};
|
||||||
@@ -486,7 +486,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ast_node(vd, VarDecl, decl);
|
ast_node(vd, VarDecl, decl);
|
||||||
Type *base_type = check_type_extra(c, vd->type, NULL, cycle_checker);
|
Type *base_type = check_type_extra(c, vd->type, NULL);
|
||||||
|
|
||||||
for_array(name_index, vd->names) {
|
for_array(name_index, vd->names) {
|
||||||
AstNode *name = vd->names.e[name_index];
|
AstNode *name = vd->names.e[name_index];
|
||||||
@@ -526,7 +526,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
}
|
}
|
||||||
ast_node(vd, VarDecl, decl);
|
ast_node(vd, VarDecl, decl);
|
||||||
|
|
||||||
Type *type = check_type_extra(c, vd->type, NULL, cycle_checker);
|
Type *type = check_type_extra(c, vd->type, NULL);
|
||||||
|
|
||||||
if (vd->is_using) {
|
if (vd->is_using) {
|
||||||
if (vd->names.count > 1) {
|
if (vd->names.count > 1) {
|
||||||
@@ -633,7 +633,7 @@ GB_COMPARE_PROC(cmp_struct_entity_size) {
|
|||||||
return xa > ya ? -1 : xa < ya;
|
return xa > ya ? -1 : xa < ya;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
||||||
GB_ASSERT(is_type_struct(struct_type));
|
GB_ASSERT(is_type_struct(struct_type));
|
||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke
|
|||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
||||||
|
|
||||||
check_fields(c, node, st->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("struct"));
|
check_fields(c, node, st->decls, fields, field_count, other_fields, other_field_count, str_lit("struct"));
|
||||||
|
|
||||||
struct_type->Record.struct_is_packed = st->is_packed;
|
struct_type->Record.struct_is_packed = st->is_packed;
|
||||||
struct_type->Record.struct_is_ordered = st->is_ordered;
|
struct_type->Record.struct_is_ordered = st->is_ordered;
|
||||||
@@ -694,7 +694,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke
|
|||||||
type_set_offsets(c->sizes, c->allocator, struct_type);
|
type_set_offsets(c->sizes, c->allocator, struct_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||||
GB_ASSERT(is_type_union(union_type));
|
GB_ASSERT(is_type_union(union_type));
|
||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
@@ -720,7 +720,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker
|
|||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
||||||
|
|
||||||
check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("union"));
|
check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, str_lit("union"));
|
||||||
|
|
||||||
union_type->Record.fields = fields;
|
union_type->Record.fields = fields;
|
||||||
union_type->Record.field_count = field_count;
|
union_type->Record.field_count = field_count;
|
||||||
@@ -728,7 +728,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker
|
|||||||
union_type->Record.other_field_count = other_field_count;
|
union_type->Record.other_field_count = other_field_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||||
GB_ASSERT(node->kind == AstNode_RawUnionType);
|
GB_ASSERT(node->kind == AstNode_RawUnionType);
|
||||||
GB_ASSERT(is_type_raw_union(union_type));
|
GB_ASSERT(is_type_raw_union(union_type));
|
||||||
ast_node(ut, RawUnionType, node);
|
ast_node(ut, RawUnionType, node);
|
||||||
@@ -755,7 +755,7 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChec
|
|||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, field_count);
|
||||||
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
Entity **other_fields = gb_alloc_array(c->allocator, Entity *, other_field_count);
|
||||||
|
|
||||||
check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, cycle_checker, str_lit("raw union"));
|
check_fields(c, node, ut->decls, fields, field_count, other_fields, other_field_count, str_lit("raw union"));
|
||||||
|
|
||||||
union_type->Record.fields = fields;
|
union_type->Record.fields = fields;
|
||||||
union_type->Record.field_count = field_count;
|
union_type->Record.field_count = field_count;
|
||||||
@@ -1017,7 +1017,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, CycleChecker *cycle_checker) {
|
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
||||||
GB_ASSERT(n->kind == AstNode_Ident);
|
GB_ASSERT(n->kind == AstNode_Ident);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
o->expr = n;
|
o->expr = n;
|
||||||
@@ -1037,13 +1037,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
|||||||
}
|
}
|
||||||
add_entity_use(c, n, e);
|
add_entity_use(c, n, e);
|
||||||
|
|
||||||
// CycleChecker local_cycle_checker = {0};
|
check_entity_decl(c, e, NULL, named_type);
|
||||||
// if (cycle_checker == NULL) {
|
|
||||||
// cycle_checker = &local_cycle_checker;
|
|
||||||
// }
|
|
||||||
// defer (cycle_checker_destroy(&local_cycle_checker));
|
|
||||||
|
|
||||||
check_entity_decl(c, e, NULL, named_type, cycle_checker);
|
|
||||||
|
|
||||||
if (e->type == NULL) {
|
if (e->type == NULL) {
|
||||||
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
|
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
|
||||||
@@ -1085,23 +1079,8 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
|||||||
|
|
||||||
case Entity_TypeName: {
|
case Entity_TypeName: {
|
||||||
o->mode = Addressing_Type;
|
o->mode = Addressing_Type;
|
||||||
#if 0
|
#if 1
|
||||||
// TODO(bill): Fix cyclical dependancy checker
|
// TODO(bill): Fix cyclical dependancy checker
|
||||||
if (cycle_checker != NULL) {
|
|
||||||
for_array(i, cycle_checker->path) {
|
|
||||||
Entity *prev = cycle_checker->path[i];
|
|
||||||
if (prev == e) {
|
|
||||||
error(e->token, "Illegal declaration cycle for %.*s", LIT(e->token.string));
|
|
||||||
for (isize j = i; j < gb_array_count(cycle_checker->path); j++) {
|
|
||||||
Entity *ref = cycle_checker->path[j];
|
|
||||||
error(ref->token, "\t%.*s refers to", LIT(ref->token.string));
|
|
||||||
}
|
|
||||||
error(e->token, "\t%.*s", LIT(e->token.string));
|
|
||||||
type = t_invalid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -1161,7 +1140,7 @@ i64 check_array_count(Checker *c, AstNode *e) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_checker) {
|
Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
|
||||||
ExactValue null_value = {ExactValue_Invalid};
|
ExactValue null_value = {ExactValue_Invalid};
|
||||||
Type *type = NULL;
|
Type *type = NULL;
|
||||||
gbString err_str = NULL;
|
gbString err_str = NULL;
|
||||||
@@ -1169,7 +1148,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
switch (e->kind) {
|
switch (e->kind) {
|
||||||
case_ast_node(i, Ident, e);
|
case_ast_node(i, Ident, e);
|
||||||
Operand o = {0};
|
Operand o = {0};
|
||||||
check_identifier(c, &o, e, named_type, cycle_checker);
|
check_identifier(c, &o, e, named_type);
|
||||||
|
|
||||||
switch (o.mode) {
|
switch (o.mode) {
|
||||||
case Addressing_Invalid:
|
case Addressing_Invalid:
|
||||||
@@ -1212,7 +1191,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pe, ParenExpr, e);
|
case_ast_node(pe, ParenExpr, e);
|
||||||
type = check_type_extra(c, pe->expr, named_type, cycle_checker);
|
type = check_type_extra(c, pe->expr, named_type);
|
||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
@@ -1240,7 +1219,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
|
|
||||||
case_ast_node(at, ArrayType, e);
|
case_ast_node(at, ArrayType, e);
|
||||||
if (at->count != NULL) {
|
if (at->count != NULL) {
|
||||||
Type *elem = check_type_extra(c, at->elem, NULL, cycle_checker);
|
Type *elem = check_type_extra(c, at->elem, NULL);
|
||||||
type = make_type_array(c->allocator, elem, check_array_count(c, at->count));
|
type = make_type_array(c->allocator, elem, check_array_count(c, at->count));
|
||||||
} else {
|
} else {
|
||||||
Type *elem = check_type(c, at->elem);
|
Type *elem = check_type(c, at->elem);
|
||||||
@@ -1266,7 +1245,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
type = make_type_struct(c->allocator);
|
type = make_type_struct(c->allocator);
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
check_open_scope(c, e);
|
check_open_scope(c, e);
|
||||||
check_struct_type(c, type, e, cycle_checker);
|
check_struct_type(c, type, e);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
goto end;
|
goto end;
|
||||||
@@ -1276,7 +1255,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
type = make_type_union(c->allocator);
|
type = make_type_union(c->allocator);
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
check_open_scope(c, e);
|
check_open_scope(c, e);
|
||||||
check_union_type(c, type, e, cycle_checker);
|
check_union_type(c, type, e);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
goto end;
|
goto end;
|
||||||
@@ -1286,7 +1265,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type, CycleChecker *c
|
|||||||
type = make_type_raw_union(c->allocator);
|
type = make_type_raw_union(c->allocator);
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
check_open_scope(c, e);
|
check_open_scope(c, e);
|
||||||
check_raw_union_type(c, type, e, cycle_checker);
|
check_raw_union_type(c, type, e);
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
type->Record.node = e;
|
type->Record.node = e;
|
||||||
goto end;
|
goto end;
|
||||||
@@ -1333,7 +1312,9 @@ end:
|
|||||||
|
|
||||||
if (is_type_named(type)) {
|
if (is_type_named(type)) {
|
||||||
if (type->Named.base == NULL) {
|
if (type->Named.base == NULL) {
|
||||||
error_node(e, "Invalid type definition");
|
gbString name = type_to_string(type);
|
||||||
|
error_node(e, "Invalid type definition of %s", name);
|
||||||
|
gb_string_free(name);
|
||||||
type->Named.base = t_invalid;
|
type->Named.base = t_invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1341,7 +1322,9 @@ end:
|
|||||||
if (is_type_typed(type)) {
|
if (is_type_typed(type)) {
|
||||||
add_type_and_value(&c->info, e, Addressing_Type, type, null_value);
|
add_type_and_value(&c->info, e, Addressing_Type, type, null_value);
|
||||||
} else {
|
} else {
|
||||||
error_node(e, "Invalid type definition");
|
gbString name = type_to_string(type);
|
||||||
|
error_node(e, "Invalid type definition of %s", name);
|
||||||
|
gb_string_free(name);
|
||||||
type = t_invalid;
|
type = t_invalid;
|
||||||
}
|
}
|
||||||
set_base_type(named_type, type);
|
set_base_type(named_type, type);
|
||||||
@@ -2581,7 +2564,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (entity->type == NULL) { // Not setup yet
|
if (entity->type == NULL) { // Not setup yet
|
||||||
check_entity_decl(c, entity, NULL, NULL, NULL);
|
check_entity_decl(c, entity, NULL, NULL);
|
||||||
}
|
}
|
||||||
GB_ASSERT(entity->type != NULL);
|
GB_ASSERT(entity->type != NULL);
|
||||||
|
|
||||||
@@ -3890,7 +3873,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(i, Ident, node);
|
case_ast_node(i, Ident, node);
|
||||||
check_identifier(c, o, node, type_hint, NULL);
|
check_identifier(c, o, node, type_hint);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(bl, BasicLit, node);
|
case_ast_node(bl, BasicLit, node);
|
||||||
|
|||||||
+1
-1
@@ -1102,7 +1102,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
d->proc_decl = node;
|
d->proc_decl = node;
|
||||||
|
|
||||||
add_entity_and_decl_info(c, pd->name, e, d);
|
add_entity_and_decl_info(c, pd->name, e, d);
|
||||||
check_entity_decl(c, e, d, NULL, NULL);
|
check_entity_decl(c, e, d, NULL);
|
||||||
#endif
|
#endif
|
||||||
case_end;
|
case_end;
|
||||||
}
|
}
|
||||||
|
|||||||
+110
-15
@@ -302,6 +302,9 @@ Type *base_type(Type *t) {
|
|||||||
if (t == NULL || t->kind != Type_Named) {
|
if (t == NULL || t->kind != Type_Named) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (t == t->Named.base) {
|
||||||
|
return t_invalid;
|
||||||
|
}
|
||||||
t = t->Named.base;
|
t = t->Named.base;
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@@ -1037,11 +1040,66 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct TypePath {
|
||||||
|
Array(Type *) path; // Entity_TypeName;
|
||||||
|
bool failure;
|
||||||
|
} TypePath;
|
||||||
|
|
||||||
|
void type_path_init(TypePath *tp) {
|
||||||
|
// TODO(bill): Use an allocator that uses a backing array if it can and then use alternative allocator when exhausted
|
||||||
|
array_init(&tp->path, heap_allocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
void type_path_free(TypePath *tp) {
|
||||||
|
array_free(&tp->path);
|
||||||
|
}
|
||||||
|
|
||||||
|
TypePath *type_path_push(TypePath *tp, Type *t) {
|
||||||
|
GB_ASSERT(tp != NULL);
|
||||||
|
|
||||||
|
for_array(i, tp->path) {
|
||||||
|
if (tp->path.e[i] == t) {
|
||||||
|
// TODO(bill):
|
||||||
|
GB_ASSERT(is_type_named(t));
|
||||||
|
Entity *e = t->Named.type_name;
|
||||||
|
error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
|
||||||
|
// NOTE(bill): Print cycle, if it's deep enough
|
||||||
|
for (isize j = 0; j < tp->path.count; j++) {
|
||||||
|
Type *t = tp->path.e[j];
|
||||||
|
GB_ASSERT(is_type_named(t));
|
||||||
|
Entity *e = t->Named.type_name;
|
||||||
|
error(e->token, "\t%.*s refers to", LIT(t->Named.name));
|
||||||
|
}
|
||||||
|
// NOTE(bill): This will only print if the path count > 1
|
||||||
|
error(e->token, "\t%.*s", LIT(t->Named.name));
|
||||||
|
tp->failure = true;
|
||||||
|
|
||||||
|
// NOTE(bill): Just quit immediately
|
||||||
|
// TODO(bill): Try and solve this gracefully
|
||||||
|
gb_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tp->failure) {
|
||||||
|
array_add(&tp->path, t);
|
||||||
|
}
|
||||||
|
return tp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void type_path_pop(TypePath *tp) {
|
||||||
|
if (tp != NULL) {
|
||||||
|
array_pop(&tp->path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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_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) {
|
||||||
if (align > 0) {
|
if (align > 0) {
|
||||||
i64 result = size + align-1;
|
i64 result = size + align-1;
|
||||||
@@ -1050,12 +1108,25 @@ i64 align_formula(i64 size, i64 align) {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||||
|
i64 align;
|
||||||
|
TypePath path = {0};
|
||||||
|
type_path_init(&path);
|
||||||
|
align = type_align_of_internal(s, allocator, t, &path);
|
||||||
|
type_path_free(&path);
|
||||||
|
return align;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FAILURE_ALIGNMENT (-1)
|
||||||
|
|
||||||
|
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(s, allocator, t->Array.elem);
|
return type_align_of_internal(s, allocator, t->Array.elem, path);
|
||||||
case Type_Vector: {
|
case Type_Vector: {
|
||||||
i64 size = type_size_of(s, allocator, t->Vector.elem);
|
i64 size = type_size_of(s, allocator, t->Vector.elem);
|
||||||
i64 count = gb_max(prev_pow2(t->Vector.count), 1);
|
i64 count = gb_max(prev_pow2(t->Vector.count), 1);
|
||||||
@@ -1066,7 +1137,7 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
case Type_Tuple: {
|
case Type_Tuple: {
|
||||||
i64 max = 1;
|
i64 max = 1;
|
||||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||||
i64 align = type_align_of(s, allocator, t->Tuple.variables[i]->type);
|
i64 align = type_align_of_internal(s, allocator, t->Tuple.variables[i]->type, path);
|
||||||
if (max < align) {
|
if (max < align) {
|
||||||
max = align;
|
max = align;
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1146,7 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Maybe:
|
case Type_Maybe:
|
||||||
return gb_max(type_align_of(s, allocator, t->Maybe.elem), type_align_of(s, allocator, t_bool));
|
return gb_max(type_align_of_internal(s, allocator, t->Maybe.elem, path), type_align_of_internal(s, allocator, t_bool, path));
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
switch (t->Record.kind) {
|
||||||
@@ -1084,23 +1155,41 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
// TODO(bill): What is this supposed to be?
|
// TODO(bill): What is this supposed to be?
|
||||||
if (t->Record.struct_is_packed) {
|
if (t->Record.struct_is_packed) {
|
||||||
i64 max = s.word_size;
|
i64 max = s.word_size;
|
||||||
for (isize i = 1; i < t->Record.field_count; i++) {
|
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||||
// NOTE(bill): field zero is null
|
Type *field_type = t->Record.fields[i]->type;
|
||||||
i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
|
type_path_push(path, field_type);
|
||||||
|
if (path->failure) {
|
||||||
|
return FAILURE_ALIGNMENT;
|
||||||
|
}
|
||||||
|
i64 align = type_align_of_internal(s, allocator, field_type, path);
|
||||||
|
type_path_pop(path);
|
||||||
if (max < align) {
|
if (max < align) {
|
||||||
max = align;
|
max = align;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
return type_align_of(s, allocator, t->Record.fields[0]->type);
|
Type *field_type = t->Record.fields[0]->type;
|
||||||
|
type_path_push(path, field_type);
|
||||||
|
if (path->failure) {
|
||||||
|
return FAILURE_ALIGNMENT;
|
||||||
|
}
|
||||||
|
i64 align = type_align_of_internal(s, allocator, field_type, path);
|
||||||
|
type_path_pop(path);
|
||||||
|
return align;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TypeRecord_Union: {
|
case TypeRecord_Union: {
|
||||||
i64 max = 1;
|
i64 max = 1;
|
||||||
|
// NOTE(bill): field zero is null
|
||||||
for (isize i = 1; i < t->Record.field_count; i++) {
|
for (isize i = 1; i < t->Record.field_count; i++) {
|
||||||
// NOTE(bill): field zero is null
|
Type *field_type = t->Record.fields[i]->type;
|
||||||
i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
|
type_path_push(path, field_type);
|
||||||
|
if (path->failure) {
|
||||||
|
return FAILURE_ALIGNMENT;
|
||||||
|
}
|
||||||
|
i64 align = type_align_of_internal(s, allocator, field_type, path);
|
||||||
|
type_path_pop(path);
|
||||||
if (max < align) {
|
if (max < align) {
|
||||||
max = align;
|
max = align;
|
||||||
}
|
}
|
||||||
@@ -1110,7 +1199,13 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
case TypeRecord_RawUnion: {
|
case TypeRecord_RawUnion: {
|
||||||
i64 max = 1;
|
i64 max = 1;
|
||||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||||
i64 align = type_align_of(s, allocator, t->Record.fields[i]->type);
|
Type *field_type = t->Record.fields[i]->type;
|
||||||
|
type_path_push(path, field_type);
|
||||||
|
if (path->failure) {
|
||||||
|
return FAILURE_ALIGNMENT;
|
||||||
|
}
|
||||||
|
i64 align = type_align_of_internal(s, allocator, field_type, path);
|
||||||
|
type_path_pop(path);
|
||||||
if (max < align) {
|
if (max < align) {
|
||||||
max = align;
|
max = align;
|
||||||
}
|
}
|
||||||
@@ -1118,7 +1213,7 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
return max;
|
return max;
|
||||||
} break;
|
} break;
|
||||||
case TypeRecord_Enum:
|
case TypeRecord_Enum:
|
||||||
return type_align_of(s, allocator, t->Record.enum_base);
|
return type_align_of_internal(s, allocator, t->Record.enum_base, path);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -1232,9 +1327,9 @@ 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);
|
||||||
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);
|
i64 size = t->Tuple.offsets[count-1] + type_size_of(s, allocator, t->Tuple.variables[count-1]->type);
|
||||||
i64 align = type_align_of(s, allocator, t);
|
|
||||||
return align_formula(size, align);
|
return align_formula(size, align);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -1245,14 +1340,15 @@ 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);
|
||||||
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(s, allocator, t->Record.fields[count-1]->type);
|
||||||
i64 align = type_align_of(s, allocator, t);
|
|
||||||
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 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++) {
|
||||||
@@ -1262,7 +1358,6 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// NOTE(bill): Align to int
|
// NOTE(bill): Align to int
|
||||||
i64 align = type_align_of(s, allocator, t);
|
|
||||||
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(s, allocator, t_int);
|
||||||
return align_formula(size, align);
|
return align_formula(size, align);
|
||||||
@@ -1270,6 +1365,7 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
|
|
||||||
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 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(s, allocator, t->Record.fields[i]->type);
|
||||||
@@ -1278,7 +1374,6 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(bill): Is this how it should work?
|
// TODO(bill): Is this how it should work?
|
||||||
i64 align = type_align_of(s, allocator, t);
|
|
||||||
return align_formula(max, align);
|
return align_formula(max, align);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -58,7 +58,7 @@ ExactValue make_exact_value_integer_from_string(String string) {
|
|||||||
// TODO(bill): Allow for numbers with underscores in them
|
// TODO(bill): Allow for numbers with underscores in them
|
||||||
ExactValue result = {ExactValue_Integer};
|
ExactValue result = {ExactValue_Integer};
|
||||||
i32 base = 10;
|
i32 base = 10;
|
||||||
if (string.text[0] == '0') {
|
if (string.len > 2 && string.text[0] == '0') {
|
||||||
switch (string.text[1]) {
|
switch (string.text[1]) {
|
||||||
case 'b': base = 2; break;
|
case 'b': base = 2; break;
|
||||||
case 'o': base = 8; break;
|
case 'o': base = 8; break;
|
||||||
|
|||||||
Reference in New Issue
Block a user