mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-23 22:25:00 -07:00
windows.odin TYPE_NAME to Type_Name; More SSA work and SSA printing for debugging
This commit is contained in:
@@ -408,6 +408,56 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
||||
}
|
||||
|
||||
|
||||
void check_alias_decl(Checker *c, Entity *e, AstNode *expr) {
|
||||
GB_ASSERT(e->type == NULL);
|
||||
GB_ASSERT(e->kind == Entity_Alias);
|
||||
|
||||
if (e->flags & EntityFlag_Visited) {
|
||||
e->type = t_invalid;
|
||||
return;
|
||||
}
|
||||
e->flags |= EntityFlag_Visited;
|
||||
e->type = t_invalid;
|
||||
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
if (expr->kind == AstNode_Alias) {
|
||||
error_node(expr, "#alias of an #alias is not allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (expr->kind == AstNode_Ident) {
|
||||
Operand o = {0};
|
||||
Entity *f = check_ident(c, &o, expr, NULL, NULL, true);
|
||||
if (f != NULL) {
|
||||
e->Alias.original = f;
|
||||
e->type = f->type;
|
||||
}
|
||||
return;
|
||||
} else if (expr->kind == AstNode_SelectorExpr) {
|
||||
Operand o = {0};
|
||||
Entity *f = check_selector(c, &o, expr, NULL);
|
||||
if (f != NULL) {
|
||||
e->Alias.original = f;
|
||||
e->type = f->type;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Operand o = {0};
|
||||
check_expr_or_type(c, &o, expr);
|
||||
if (o.mode == Addressing_Invalid) {
|
||||
return;
|
||||
}
|
||||
switch (o.mode) {
|
||||
case Addressing_Type:
|
||||
e->type = o.type;
|
||||
break;
|
||||
default:
|
||||
error_node(expr, "#alias declarations only allow types");
|
||||
}
|
||||
}
|
||||
|
||||
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||
if (e->type != NULL) {
|
||||
return;
|
||||
@@ -443,6 +493,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
|
||||
case Entity_Procedure:
|
||||
check_proc_lit(c, e, d);
|
||||
break;
|
||||
case Entity_Alias:
|
||||
check_alias_decl(c, e, d->init_expr);
|
||||
break;
|
||||
}
|
||||
|
||||
c->context = prev;
|
||||
|
||||
+30
-16
@@ -1028,7 +1028,7 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||
}
|
||||
|
||||
|
||||
void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint) {
|
||||
Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *type_hint, bool allow_import_name) {
|
||||
GB_ASSERT(n->kind == AstNode_Ident);
|
||||
o->mode = Addressing_Invalid;
|
||||
o->expr = n;
|
||||
@@ -1046,7 +1046,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
|
||||
if (named_type != NULL) {
|
||||
set_base_type(named_type, t_invalid);
|
||||
}
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool is_overloaded = false;
|
||||
@@ -1095,7 +1095,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
|
||||
o->type = t_invalid;
|
||||
o->overload_count = overload_count;
|
||||
o->overload_entities = procs;
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
gb_free(heap_allocator(), procs);
|
||||
}
|
||||
@@ -1106,20 +1106,26 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
|
||||
|
||||
if (e->type == NULL) {
|
||||
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(name));
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e->flags |= EntityFlag_Used;
|
||||
|
||||
Entity *original_e = e;
|
||||
while (e->kind == Entity_Alias && e->Alias.original != NULL) {
|
||||
e = e->Alias.original;
|
||||
}
|
||||
|
||||
Type *type = e->type;
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_Constant:
|
||||
if (type == t_invalid) {
|
||||
o->type = t_invalid;
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
o->value = e->Constant.value;
|
||||
if (o->value.kind == ExactValue_Invalid) {
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
o->mode = Addressing_Constant;
|
||||
break;
|
||||
@@ -1128,7 +1134,7 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
|
||||
e->flags |= EntityFlag_Used;
|
||||
if (type == t_invalid) {
|
||||
o->type = t_invalid;
|
||||
return;
|
||||
return e;
|
||||
}
|
||||
o->mode = Addressing_Variable;
|
||||
if (e->Variable.is_immutable) {
|
||||
@@ -1151,22 +1157,25 @@ void check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type *typ
|
||||
break;
|
||||
|
||||
case Entity_ImportName:
|
||||
error_node(n, "Use of import `%.*s` not in selector", LIT(e->ImportName.name));
|
||||
return;
|
||||
if (!allow_import_name) {
|
||||
error_node(n, "Use of import `%.*s` not in selector", LIT(name));
|
||||
}
|
||||
return e;
|
||||
case Entity_LibraryName:
|
||||
error_node(n, "Use of library `%.*s` not in #foreign tag", LIT(e->LibraryName.name));
|
||||
return;
|
||||
error_node(n, "Use of library `%.*s` not in #foreign tag", LIT(name));
|
||||
return e;
|
||||
|
||||
case Entity_Nil:
|
||||
o->mode = Addressing_Value;
|
||||
break;
|
||||
|
||||
default:
|
||||
compiler_error("Compiler error: Unknown EntityKind");
|
||||
compiler_error("Unknown EntityKind");
|
||||
break;
|
||||
}
|
||||
|
||||
o->type = type;
|
||||
return e;
|
||||
}
|
||||
|
||||
i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) {
|
||||
@@ -1342,7 +1351,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
|
||||
switch (e->kind) {
|
||||
case_ast_node(i, Ident, e);
|
||||
Operand o = {0};
|
||||
check_ident(c, &o, e, named_type, NULL);
|
||||
check_ident(c, &o, e, named_type, NULL, false);
|
||||
|
||||
switch (o.mode) {
|
||||
case Addressing_Invalid:
|
||||
@@ -2679,6 +2688,11 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h
|
||||
add_entity_use(c, op_expr, e);
|
||||
expr_entity = e;
|
||||
|
||||
Entity *original_e = e;
|
||||
while (e->kind == Entity_Alias && e->Alias.original != NULL) {
|
||||
e = e->Alias.original;
|
||||
}
|
||||
|
||||
if (e != NULL && e->kind == Entity_ImportName && selector->kind == AstNode_Ident) {
|
||||
// IMPORTANT NOTE(bill): This is very sloppy code but it's also very fragile
|
||||
// It pretty much needs to be in this order and this way
|
||||
@@ -4413,7 +4427,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
||||
case_end;
|
||||
|
||||
case_ast_node(i, Ident, node);
|
||||
check_ident(c, o, node, NULL, type_hint);
|
||||
check_ident(c, o, node, NULL, type_hint, false);
|
||||
case_end;
|
||||
|
||||
case_ast_node(bl, BasicLit, node);
|
||||
@@ -5626,7 +5640,7 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(ht, HelperType, node);
|
||||
str = gb_string_appendc(str, "type ");
|
||||
str = gb_string_appendc(str, "#type ");
|
||||
str = write_expr_to_string(str, ht->type);
|
||||
case_end;
|
||||
}
|
||||
|
||||
+8
-3
@@ -816,7 +816,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
||||
return false;
|
||||
}
|
||||
error(entity->token,
|
||||
"Redeclararation of `%.*s` in this scope through `using`\n"
|
||||
"Redeclaration of `%.*s` in this scope through `using`\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name),
|
||||
LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column);
|
||||
@@ -827,7 +827,7 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
|
||||
return false;
|
||||
}
|
||||
error(entity->token,
|
||||
"Redeclararation of `%.*s` in this scope\n"
|
||||
"Redeclaration of `%.*s` in this scope\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(name),
|
||||
LIT(pos.file), pos.line, pos.column);
|
||||
@@ -1467,7 +1467,12 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
|
||||
// TODO(bill): What if vd->type != NULL??? How to handle this case?
|
||||
d->type_expr = init;
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
} else if (up_init != NULL && up_init->kind == AstNode_Alias) {
|
||||
error_node(up_init, "#alias declarations are not yet supported");
|
||||
continue;
|
||||
// e = make_entity_alias(c->allocator, d->scope, name->Ident, NULL, NULL);
|
||||
// d->init_expr = init->Alias.expr;
|
||||
}else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_lit = up_init;
|
||||
d->type_expr = vd->type;
|
||||
|
||||
@@ -13,6 +13,7 @@ typedef struct Type Type;
|
||||
ENTITY_KIND(Builtin) \
|
||||
ENTITY_KIND(ImportName) \
|
||||
ENTITY_KIND(LibraryName) \
|
||||
ENTITY_KIND(Alias) \
|
||||
ENTITY_KIND(Nil) \
|
||||
ENTITY_KIND(Count)
|
||||
|
||||
@@ -95,6 +96,9 @@ struct Entity {
|
||||
String name;
|
||||
bool used;
|
||||
} LibraryName;
|
||||
struct {
|
||||
Entity *original;
|
||||
} Alias;
|
||||
i32 Nil;
|
||||
};
|
||||
};
|
||||
@@ -218,6 +222,13 @@ Entity *make_entity_library_name(gbAllocator a, Scope *scope, Token token, Type
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_alias(gbAllocator a, Scope *scope, Token token, Type *type,
|
||||
Entity *original) {
|
||||
Entity *entity = alloc_entity(a, Entity_Alias, scope, token, type);
|
||||
entity->Alias.original = original;
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_nil(gbAllocator a, String name, Type *type) {
|
||||
Token token = make_token_ident(name);
|
||||
Entity *entity = alloc_entity(a, Entity_Nil, NULL, token, type);
|
||||
|
||||
@@ -806,6 +806,10 @@ GB_DEF void const *gb_memchr (void const *data, u8 byte_value, isize size);
|
||||
GB_DEF void const *gb_memrchr (void const *data, u8 byte_value, isize size);
|
||||
|
||||
|
||||
#ifndef gb_memcopy_array
|
||||
#define gb_memcopy_array(dst, src, count) gb_memcopy((dst), (src), gb_size_of(*(dst))*(count))
|
||||
#endif
|
||||
|
||||
// NOTE(bill): Very similar to doing `*cast(T *)(&u)`
|
||||
#ifndef GB_BIT_CAST
|
||||
#define GB_BIT_CAST(dest, source) do { \
|
||||
|
||||
@@ -2916,8 +2916,21 @@ irValue *ir_find_global_variable(irProcedure *proc, String name) {
|
||||
|
||||
void ir_build_stmt_list(irProcedure *proc, AstNodeArray stmts);
|
||||
|
||||
irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv) {
|
||||
|
||||
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(expr));
|
||||
GB_ASSERT_NOT_NULL(tv);
|
||||
|
||||
if (tv->value.kind != ExactValue_Invalid) {
|
||||
return ir_add_module_constant(proc->module, tv->type, tv->value);
|
||||
}
|
||||
|
||||
if (tv->mode == Addressing_Variable) {
|
||||
return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
}
|
||||
|
||||
switch (expr->kind) {
|
||||
case_ast_node(bl, BasicLit, expr);
|
||||
TokenPos pos = bl->pos;
|
||||
@@ -3782,27 +3795,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
TypeAndValue *tv = map_tav_get(&proc->module->info->types, hash_pointer(expr));
|
||||
GB_ASSERT_NOT_NULL(tv);
|
||||
|
||||
if (tv->value.kind != ExactValue_Invalid) {
|
||||
return ir_add_module_constant(proc->module, tv->type, tv->value);
|
||||
}
|
||||
|
||||
irValue *value = NULL;
|
||||
if (tv->mode == Addressing_Variable) {
|
||||
value = ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
} else {
|
||||
value = ir_build_single_expr(proc, expr, tv);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
irValue *ir_get_using_variable(irProcedure *proc, Entity *e) {
|
||||
GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous);
|
||||
String name = e->token.string;
|
||||
@@ -5192,9 +5184,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
if (fs->cond != NULL) {
|
||||
loop = ir_new_block(proc, node, "for.loop");
|
||||
}
|
||||
irBlock *cont = loop;
|
||||
irBlock *post = loop;
|
||||
if (fs->post != NULL) {
|
||||
cont = ir_new_block(proc, node, "for.post");
|
||||
post = ir_new_block(proc, node, "for.post");
|
||||
}
|
||||
ir_emit_jump(proc, loop);
|
||||
ir_start_block(proc, loop);
|
||||
@@ -5204,7 +5196,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
ir_start_block(proc, body);
|
||||
}
|
||||
|
||||
ir_push_target_list(proc, done, cont, NULL);
|
||||
ir_push_target_list(proc, done, post, NULL);
|
||||
|
||||
ir_open_scope(proc);
|
||||
ir_build_stmt(proc, fs->body);
|
||||
@@ -5212,10 +5204,10 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
|
||||
ir_pop_target_list(proc);
|
||||
|
||||
ir_emit_jump(proc, cont);
|
||||
ir_emit_jump(proc, post);
|
||||
|
||||
if (fs->post != NULL) {
|
||||
ir_start_block(proc, cont);
|
||||
ir_start_block(proc, post);
|
||||
ir_build_stmt(proc, fs->post);
|
||||
ir_emit_jump(proc, loop);
|
||||
}
|
||||
@@ -5646,7 +5638,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(pa, PushContext, node);
|
||||
case_ast_node(pc, PushContext, node);
|
||||
ir_emit_comment(proc, str_lit("PushContext"));
|
||||
ir_open_scope(proc);
|
||||
|
||||
@@ -5656,9 +5648,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
|
||||
ir_add_defer_instr(proc, proc->scope_index, ir_instr_store(proc, context_ptr, ir_emit_load(proc, prev_context)));
|
||||
|
||||
ir_emit_store(proc, context_ptr, ir_build_expr(proc, pa->expr));
|
||||
ir_emit_store(proc, context_ptr, ir_build_expr(proc, pc->expr));
|
||||
|
||||
ir_build_stmt(proc, pa->body);
|
||||
ir_build_stmt(proc, pc->body);
|
||||
|
||||
ir_close_scope(proc, irDeferExit_Default, NULL);
|
||||
case_end;
|
||||
|
||||
@@ -139,6 +139,10 @@ AstNodeArray make_ast_node_array(AstFile *f) {
|
||||
AstNodeArray elems; \
|
||||
Token open, close; \
|
||||
}) \
|
||||
AST_NODE_KIND(Alias, "alias", struct { \
|
||||
Token token; \
|
||||
AstNode *expr; \
|
||||
}) \
|
||||
AST_NODE_KIND(_ExprBegin, "", i32) \
|
||||
AST_NODE_KIND(BadExpr, "bad expression", struct { Token begin, end; }) \
|
||||
AST_NODE_KIND(TagExpr, "tag expression", struct { Token token, name; AstNode *expr; }) \
|
||||
@@ -445,6 +449,8 @@ Token ast_node_token(AstNode *node) {
|
||||
return ast_node_token(node->CompoundLit.type);
|
||||
}
|
||||
return node->CompoundLit.open;
|
||||
case AstNode_Alias: return node->Alias.token;
|
||||
|
||||
case AstNode_TagExpr: return node->TagExpr.token;
|
||||
case AstNode_RunExpr: return node->RunExpr.token;
|
||||
case AstNode_BadExpr: return node->BadExpr.begin;
|
||||
@@ -771,6 +777,13 @@ AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token o
|
||||
result->CompoundLit.close = close;
|
||||
return result;
|
||||
}
|
||||
AstNode *ast_alias(AstFile *f, Token token, AstNode *expr) {
|
||||
AstNode *result = make_ast_node(f, AstNode_Alias);
|
||||
result->Alias.token = token;
|
||||
result->Alias.expr = expr;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) {
|
||||
AstNode *result = make_ast_node(f, AstNode_TernaryExpr);
|
||||
@@ -1762,6 +1775,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
} else if (str_eq(name.string, str_lit("line"))) { return ast_basic_directive(f, token, name.string);
|
||||
} else if (str_eq(name.string, str_lit("procedure"))) { return ast_basic_directive(f, token, name.string);
|
||||
} else if (str_eq(name.string, str_lit("type"))) { return ast_helper_type(f, token, parse_type(f));
|
||||
} else if (!lhs && str_eq(name.string, str_lit("alias"))) { return ast_alias(f, token, parse_expr(f, false));
|
||||
} else {
|
||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user