mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 22:28:46 +00:00
build_dll; Require an entry point procedure main
This commit is contained in:
+42
-8
@@ -292,9 +292,17 @@ bool decl_info_has_init(DeclInfo *d) {
|
||||
return true;
|
||||
}
|
||||
if (d->proc_decl != NULL) {
|
||||
ast_node(pd, ProcDecl, d->proc_decl);
|
||||
if (pd->body != NULL) {
|
||||
return true;
|
||||
switch (d->proc_decl->kind) {
|
||||
case_ast_node(pd, ProcDecl, d->proc_decl);
|
||||
if (pd->body != NULL) {
|
||||
return true;
|
||||
}
|
||||
case_end;
|
||||
case_ast_node(pd, ProcLit, d->proc_decl);
|
||||
if (pd->body != NULL) {
|
||||
return true;
|
||||
}
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,12 +957,15 @@ MapEntity generate_minimum_dependency_map(CheckerInfo *info, Entity *start) {
|
||||
MapEntity map = {0}; // Key: Entity *
|
||||
map_entity_init(&map, heap_allocator());
|
||||
|
||||
for_array(i, info->entities.entries) {
|
||||
MapDeclInfoEntry *entry = &info->entities.entries.e[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
for_array(i, info->definitions.entries) {
|
||||
Entity *e = info->definitions.entries.e[i].value;
|
||||
if (e->scope->is_global) {
|
||||
// NOTE(bill): Require runtime stuff
|
||||
add_dependency_to_map(&map, info, e);
|
||||
} else if (e->kind == Entity_Procedure) {
|
||||
if ((e->Procedure.tags & ProcTag_export) != 0) {
|
||||
add_dependency_to_map(&map, info, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1189,7 +1200,7 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
||||
case_ast_node(pd, ProcDecl, decl);
|
||||
ast_node(n, Ident, pd->name);
|
||||
Token token = *n;
|
||||
Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL);
|
||||
Entity *e = make_entity_procedure(c->allocator, parent_scope, token, NULL, pd->tags);
|
||||
e->identifier = pd->name;
|
||||
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
|
||||
d->proc_decl = decl;
|
||||
@@ -1386,7 +1397,6 @@ void check_parsed_files(Checker *c) {
|
||||
|
||||
check_import_entities(c, &file_scopes);
|
||||
|
||||
map_scope_destroy(&file_scopes);
|
||||
|
||||
check_all_global_entities(c);
|
||||
init_preload(c); // NOTE(bill): This could be setup previously through the use of `type_info(_of_val)`
|
||||
@@ -1473,6 +1483,30 @@ void check_parsed_files(Checker *c) {
|
||||
i64 align = type_align_of(c->sizes, c->allocator, e->type);
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, file_scopes.entries) {
|
||||
Scope *s = file_scopes.entries.e[i].value;
|
||||
if (s->is_init) {
|
||||
Entity *e = current_scope_lookup_entity(s, str_lit("main"));
|
||||
if (e == NULL) {
|
||||
Token token = {0};
|
||||
if (s->file->tokens.count > 0) {
|
||||
token = s->file->tokens.e[0];
|
||||
} else {
|
||||
token.pos.file = s->file->tokenizer.fullpath;
|
||||
token.pos.line = 1;
|
||||
token.pos.column = 1;
|
||||
}
|
||||
|
||||
error(token, "Undefined entry point procedure `main`");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
map_scope_destroy(&file_scopes);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-11
@@ -139,8 +139,9 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
||||
Type *init_type = NULL;
|
||||
if (vd->type) {
|
||||
init_type = check_type_extra(c, vd->type, NULL);
|
||||
if (init_type == NULL)
|
||||
if (init_type == NULL) {
|
||||
init_type = t_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < entity_count; i++) {
|
||||
@@ -180,7 +181,9 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||
|
||||
if (operand->mode != Addressing_Constant) {
|
||||
// TODO(bill): better error
|
||||
error_node(operand->expr, "`%.*s` is not a constant", LIT(ast_node_token(operand->expr).string));
|
||||
gbString str = expr_to_string(operand->expr);
|
||||
error_node(operand->expr, "`%s` is not a constant", str);
|
||||
gb_string_free(str);
|
||||
if (e->type == NULL) {
|
||||
e->type = t_invalid;
|
||||
}
|
||||
@@ -306,7 +309,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
check_procedure_type(c, proc_type, pd->type);
|
||||
|
||||
bool is_foreign = (pd->tags & ProcTag_foreign) != 0;
|
||||
bool is_link_name = (pd->tags & ProcTag_link_name) != 0;
|
||||
bool is_export = (pd->tags & ProcTag_export) != 0;
|
||||
bool is_inline = (pd->tags & ProcTag_inline) != 0;
|
||||
bool is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
|
||||
|
||||
@@ -315,10 +318,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
if (proc_type != NULL) {
|
||||
TypeProc *pt = &proc_type->Proc;
|
||||
if (pt->param_count != 0 ||
|
||||
pt->result_count) {
|
||||
pt->result_count != 0) {
|
||||
gbString str = type_to_string(proc_type);
|
||||
error(e->token,
|
||||
"Procedure type of `main` was expected to be `proc()`, got %s", str);
|
||||
error(e->token, "Procedure type of `main` was expected to be `proc()`, got %s", str);
|
||||
gb_string_free(str);
|
||||
}
|
||||
}
|
||||
@@ -328,8 +330,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
error_node(pd->type, "You cannot apply both `inline` and `no_inline` to a procedure");
|
||||
}
|
||||
|
||||
if (is_foreign && is_link_name) {
|
||||
error_node(pd->type, "You cannot apply both `foreign` and `link_name` to a procedure");
|
||||
if (is_foreign && is_export) {
|
||||
error_node(pd->type, "You cannot apply both `foreign` and `export_name` to a procedure");
|
||||
}
|
||||
|
||||
if (pd->body != NULL) {
|
||||
@@ -350,6 +352,10 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
if (proc_decl->foreign_name.len > 0) {
|
||||
name = proc_decl->foreign_name;
|
||||
}
|
||||
|
||||
e->Procedure.is_foreign = true;
|
||||
e->Procedure.foreign_name = name;
|
||||
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_entity_get(fp, key);
|
||||
if (found) {
|
||||
@@ -366,10 +372,12 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
} else {
|
||||
map_entity_set(fp, key, e);
|
||||
}
|
||||
} else if (is_link_name) {
|
||||
} else if (is_export) {
|
||||
MapEntity *fp = &c->info.foreign_procs;
|
||||
AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl;
|
||||
String name = proc_decl->link_name;
|
||||
String name = proc_decl->export_name;
|
||||
|
||||
e->Procedure.export_name = name;
|
||||
|
||||
HashKey key = hash_string(name);
|
||||
Entity **found = map_entity_get(fp, key);
|
||||
@@ -377,7 +385,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||
Entity *f = *found;
|
||||
TokenPos pos = f->token.pos;
|
||||
error_node(d->proc_decl,
|
||||
"Non unique #link_name for procedure `%.*s`\n"
|
||||
"Non unique #export name for procedure `%.*s`\n"
|
||||
"\tother at %.*s(%td:%td)",
|
||||
LIT(name), LIT(pos.file), pos.line, pos.column);
|
||||
} else {
|
||||
|
||||
@@ -59,7 +59,12 @@ struct Entity {
|
||||
i32 field_src_index;
|
||||
} Variable;
|
||||
i32 TypeName;
|
||||
i32 Procedure;
|
||||
struct {
|
||||
bool is_foreign;
|
||||
String foreign_name;
|
||||
String export_name;
|
||||
u64 tags;
|
||||
} Procedure;
|
||||
struct {
|
||||
BuiltinProcId id;
|
||||
} Builtin;
|
||||
@@ -138,8 +143,9 @@ Entity *make_entity_vector_elem(gbAllocator a, Scope *scope, Token token, Type *
|
||||
return entity;
|
||||
}
|
||||
|
||||
Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type) {
|
||||
Entity *make_entity_procedure(gbAllocator a, Scope *scope, Token token, Type *signature_type, u64 tags) {
|
||||
Entity *entity = alloc_entity(a, Entity_Procedure, scope, token, signature_type);
|
||||
entity->Procedure.tags = tags;
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
+8
-6
@@ -22,8 +22,9 @@ gb_inline Type *check_type(Checker *c, AstNode *expression) {
|
||||
|
||||
|
||||
typedef struct DelayedEntity {
|
||||
Entity *entity;
|
||||
DeclInfo *decl;
|
||||
AstNode * ident;
|
||||
Entity * entity;
|
||||
DeclInfo * decl;
|
||||
} DelayedEntity;
|
||||
|
||||
typedef struct DelayedOtherFields {
|
||||
@@ -104,7 +105,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
|
||||
DelayedEntity delay = {e, d};
|
||||
DelayedEntity delay = {name, e, d};
|
||||
array_add(delayed_entities, delay);
|
||||
}
|
||||
|
||||
@@ -181,7 +182,7 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
|
||||
add_entity_and_decl_info(c, td->name, e, d);
|
||||
|
||||
DelayedEntity delay = {e, d};
|
||||
DelayedEntity delay = {td->name, e, d};
|
||||
array_add(delayed_entities, delay);
|
||||
|
||||
|
||||
@@ -231,6 +232,7 @@ void check_scope_decls(Checker *c, AstNodeArray nodes, isize reserve_size, Delay
|
||||
for_array(i, delayed_entities) {
|
||||
DelayedEntity delayed = delayed_entities.e[i];
|
||||
if (delayed.entity->kind == Entity_Constant) {
|
||||
add_entity_and_decl_info(c, delayed.ident, delayed.entity, delayed.decl);
|
||||
check_entity_decl(c, delayed.entity, delayed.decl, NULL);
|
||||
}
|
||||
}
|
||||
@@ -1480,7 +1482,7 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa
|
||||
case Basic_i16:
|
||||
case Basic_i32:
|
||||
case Basic_i64:
|
||||
case Basic_i128:
|
||||
// case Basic_i128:
|
||||
case Basic_int:
|
||||
return gb_is_between(i, -imax, imax-1);
|
||||
|
||||
@@ -1488,7 +1490,7 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa
|
||||
case Basic_u16:
|
||||
case Basic_u32:
|
||||
case Basic_u64:
|
||||
case Basic_u128:
|
||||
// case Basic_u128:
|
||||
case Basic_uint:
|
||||
return !(u < 0 || u > umax);
|
||||
|
||||
|
||||
+1
-1
@@ -1095,7 +1095,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
#if 1
|
||||
// NOTE(bill): This must be handled here so it has access to the parent scope stuff
|
||||
// e.g. using
|
||||
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL);
|
||||
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL, pd->tags);
|
||||
e->identifier = pd->name;
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, e->scope);
|
||||
|
||||
+6
-6
@@ -11,8 +11,8 @@ typedef enum BasicKind {
|
||||
Basic_u32,
|
||||
Basic_i64,
|
||||
Basic_u64,
|
||||
Basic_i128,
|
||||
Basic_u128,
|
||||
// Basic_i128,
|
||||
// Basic_u128,
|
||||
// Basic_f16,
|
||||
Basic_f32,
|
||||
Basic_f64,
|
||||
@@ -205,8 +205,8 @@ gb_global Type basic_types[] = {
|
||||
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, 4, STR_LIT("u32")}},
|
||||
{Type_Basic, {Basic_i64, BasicFlag_Integer, 8, STR_LIT("i64")}},
|
||||
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, 8, STR_LIT("u64")}},
|
||||
{Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
|
||||
{Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
|
||||
// {Type_Basic, {Basic_i128, BasicFlag_Integer, 16, STR_LIT("i128")}},
|
||||
// {Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, 16, STR_LIT("u128")}},
|
||||
// {Type_Basic, {Basic_f16, BasicFlag_Float, 2, STR_LIT("f16")}},
|
||||
{Type_Basic, {Basic_f32, BasicFlag_Float, 4, STR_LIT("f32")}},
|
||||
{Type_Basic, {Basic_f64, BasicFlag_Float, 8, STR_LIT("f64")}},
|
||||
@@ -239,8 +239,8 @@ gb_global Type *t_i32 = &basic_types[Basic_i32];
|
||||
gb_global Type *t_u32 = &basic_types[Basic_u32];
|
||||
gb_global Type *t_i64 = &basic_types[Basic_i64];
|
||||
gb_global Type *t_u64 = &basic_types[Basic_u64];
|
||||
gb_global Type *t_i128 = &basic_types[Basic_i128];
|
||||
gb_global Type *t_u128 = &basic_types[Basic_u128];
|
||||
// gb_global Type *t_i128 = &basic_types[Basic_i128];
|
||||
// gb_global Type *t_u128 = &basic_types[Basic_u128];
|
||||
// gb_global Type *t_f16 = &basic_types[Basic_f16];
|
||||
gb_global Type *t_f32 = &basic_types[Basic_f32];
|
||||
gb_global Type *t_f64 = &basic_types[Basic_f64];
|
||||
|
||||
Reference in New Issue
Block a user