mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Begin work to move entry point code to Odin itself rather than in C++ side
This commit is contained in:
@@ -197,3 +197,8 @@ type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
|
|||||||
|
|
||||||
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
|
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
|
||||||
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
|
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
|
||||||
|
|
||||||
|
|
||||||
|
// Internal compiler use only
|
||||||
|
|
||||||
|
__entry_point :: proc() ---
|
||||||
@@ -219,6 +219,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
|||||||
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
|
GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_name));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case BuiltinProc___entry_point:
|
||||||
|
operand->mode = Addressing_NoValue;
|
||||||
|
operand->type = nullptr;
|
||||||
|
mpmc_enqueue(&c->info->intrinsics_entry_point_usage, call);
|
||||||
|
break;
|
||||||
|
|
||||||
case BuiltinProc_DIRECTIVE: {
|
case BuiltinProc_DIRECTIVE: {
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name.string;
|
String name = bd->name.string;
|
||||||
|
|||||||
+20
-16
@@ -777,21 +777,23 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
|
|
||||||
|
|
||||||
if (e->pkg != nullptr && e->token.string == "main") {
|
if (e->pkg != nullptr && e->token.string == "main") {
|
||||||
if (pt->param_count != 0 ||
|
if (e->pkg->kind != Package_Runtime) {
|
||||||
pt->result_count != 0) {
|
if (pt->param_count != 0 ||
|
||||||
gbString str = type_to_string(proc_type);
|
pt->result_count != 0) {
|
||||||
error(e->token, "Procedure type of 'main' was expected to be 'proc()', got %s", str);
|
gbString str = type_to_string(proc_type);
|
||||||
gb_string_free(str);
|
error(e->token, "Procedure type of 'main' was expected to be 'proc()', got %s", str);
|
||||||
}
|
gb_string_free(str);
|
||||||
if (pt->calling_convention != default_calling_convention()) {
|
}
|
||||||
error(e->token, "Procedure 'main' cannot have a custom calling convention");
|
if (pt->calling_convention != default_calling_convention()) {
|
||||||
}
|
error(e->token, "Procedure 'main' cannot have a custom calling convention");
|
||||||
pt->calling_convention = default_calling_convention();
|
}
|
||||||
if (e->pkg->kind == Package_Init) {
|
pt->calling_convention = default_calling_convention();
|
||||||
if (ctx->info->entry_point != nullptr) {
|
if (e->pkg->kind == Package_Init) {
|
||||||
error(e->token, "Redeclaration of the entry pointer procedure 'main'");
|
if (ctx->info->entry_point != nullptr) {
|
||||||
} else {
|
error(e->token, "Redeclaration of the entry pointer procedure 'main'");
|
||||||
ctx->info->entry_point = e;
|
} else {
|
||||||
|
ctx->info->entry_point = e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,7 +926,9 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
|||||||
"\tother at %s",
|
"\tother at %s",
|
||||||
LIT(name), token_pos_to_string(pos));
|
LIT(name), token_pos_to_string(pos));
|
||||||
} else if (name == "main") {
|
} else if (name == "main") {
|
||||||
error(d->proc_lit, "The link name 'main' is reserved for internal use");
|
if (d->entity->pkg->kind != Package_Runtime) {
|
||||||
|
error(d->proc_lit, "The link name 'main' is reserved for internal use");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
string_map_set(fp, key, e);
|
string_map_set(fp, key, e);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-5
@@ -823,6 +823,7 @@ void init_universal(void) {
|
|||||||
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
|
add_global_bool_constant("ODIN_NO_CRT", bc->no_crt);
|
||||||
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
|
add_global_bool_constant("ODIN_USE_SEPARATE_MODULES", bc->use_separate_modules);
|
||||||
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
|
add_global_bool_constant("ODIN_TEST", bc->command_kind == Command_test);
|
||||||
|
add_global_bool_constant("ODIN_NO_ENTRY_POINT", bc->no_entry_point);
|
||||||
|
|
||||||
|
|
||||||
// Builtin Procedures
|
// Builtin Procedures
|
||||||
@@ -941,6 +942,8 @@ void init_checker_info(CheckerInfo *i) {
|
|||||||
mutex_init(&i->foreign_mutex);
|
mutex_init(&i->foreign_mutex);
|
||||||
|
|
||||||
semaphore_init(&i->collect_semaphore);
|
semaphore_init(&i->collect_semaphore);
|
||||||
|
|
||||||
|
mpmc_init(&i->intrinsics_entry_point_usage, a, 1<<10); // just waste some memory here, even if it probably never used
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy_checker_info(CheckerInfo *i) {
|
void destroy_checker_info(CheckerInfo *i) {
|
||||||
@@ -3677,11 +3680,6 @@ void check_single_global_entity(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
error(e->token, "'main' is reserved as the entry point procedure in the initial scope");
|
error(e->token, "'main' is reserved as the entry point procedure in the initial scope");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (pkg->kind == Package_Runtime) {
|
|
||||||
if (e->token.string == "main") {
|
|
||||||
error(e->token, "'main' is reserved as the entry point procedure in the initial scope");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_entity_decl(ctx, e, d, nullptr);
|
check_entity_decl(ctx, e, d, nullptr);
|
||||||
@@ -5437,5 +5435,15 @@ void check_parsed_files(Checker *c) {
|
|||||||
TIME_SECTION("sort init procedures");
|
TIME_SECTION("sort init procedures");
|
||||||
check_sort_init_procedures(c);
|
check_sort_init_procedures(c);
|
||||||
|
|
||||||
|
if (c->info.intrinsics_entry_point_usage.count > 0) {
|
||||||
|
TIME_SECTION("check intrinsics.__entry_point usage");
|
||||||
|
Ast *node = nullptr;
|
||||||
|
while (mpmc_dequeue(&c->info.intrinsics_entry_point_usage, &node)) {
|
||||||
|
if (c->info.entry_point == nullptr && node != nullptr) {
|
||||||
|
warning(node, "usage of intrinsics.__entry_point will be a no-op");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TIME_SECTION("type check finish");
|
TIME_SECTION("type check finish");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -338,6 +338,9 @@ struct CheckerInfo {
|
|||||||
MPMCQueue<Entity *> required_global_variable_queue;
|
MPMCQueue<Entity *> required_global_variable_queue;
|
||||||
MPMCQueue<Entity *> required_foreign_imports_through_force_queue;
|
MPMCQueue<Entity *> required_foreign_imports_through_force_queue;
|
||||||
|
|
||||||
|
MPMCQueue<Ast *> intrinsics_entry_point_usage;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheckerContext {
|
struct CheckerContext {
|
||||||
|
|||||||
@@ -250,6 +250,8 @@ BuiltinProc__type_simple_boolean_end,
|
|||||||
|
|
||||||
BuiltinProc__type_end,
|
BuiltinProc__type_end,
|
||||||
|
|
||||||
|
BuiltinProc___entry_point,
|
||||||
|
|
||||||
BuiltinProc_COUNT,
|
BuiltinProc_COUNT,
|
||||||
};
|
};
|
||||||
gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||||
@@ -498,5 +500,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("type_equal_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
{STR_LIT("type_hasher_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
|
|
||||||
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||||
|
|
||||||
|
{STR_LIT("__entry_point"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||||
};
|
};
|
||||||
|
|||||||
+10
-5
@@ -873,7 +873,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime)
|
|||||||
} else {
|
} else {
|
||||||
if (m->info->entry_point != nullptr) {
|
if (m->info->entry_point != nullptr) {
|
||||||
lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point);
|
lbValue entry_point = lb_find_procedure_value_from_entity(m, m->info->entry_point);
|
||||||
lb_emit_call(p, entry_point, {});
|
lb_emit_call(p, entry_point, {}, ProcInlining_no_inline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1408,6 +1408,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
Entity *entry_point = info->entry_point;
|
Entity *entry_point = info->entry_point;
|
||||||
bool has_dll_main = false;
|
bool has_dll_main = false;
|
||||||
bool has_win_main = false;
|
bool has_win_main = false;
|
||||||
|
bool already_has_entry_point = false;
|
||||||
|
|
||||||
for_array(i, info->entities) {
|
for_array(i, info->entities) {
|
||||||
Entity *e = info->entities[i];
|
Entity *e = info->entities[i];
|
||||||
@@ -1425,7 +1426,9 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
if (e->Procedure.is_export ||
|
if (e->Procedure.is_export ||
|
||||||
(e->Procedure.link_name.len > 0) ||
|
(e->Procedure.link_name.len > 0) ||
|
||||||
((e->scope->flags&ScopeFlag_File) && e->Procedure.link_name.len > 0)) {
|
((e->scope->flags&ScopeFlag_File) && e->Procedure.link_name.len > 0)) {
|
||||||
if (!has_dll_main && name == "DllMain") {
|
if (name == "main" || name == "DllMain" || name == "WinMain" || name == "mainCRTStartup") {
|
||||||
|
already_has_entry_point = true;
|
||||||
|
} else if (!has_dll_main && name == "DllMain") {
|
||||||
has_dll_main = true;
|
has_dll_main = true;
|
||||||
} else if (!has_win_main && name == "WinMain") {
|
} else if (!has_win_main && name == "WinMain") {
|
||||||
has_win_main = true;
|
has_win_main = true;
|
||||||
@@ -1643,9 +1646,11 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
|
if (!already_has_entry_point) {
|
||||||
TIME_SECTION("LLVM main");
|
if (!(build_context.build_mode == BuildMode_DynamicLibrary && !has_dll_main)) {
|
||||||
lb_create_main_procedure(default_module, startup_runtime);
|
TIME_SECTION("LLVM main");
|
||||||
|
lb_create_main_procedure(default_module, startup_runtime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for_array(j, gen->modules.entries) {
|
for_array(j, gen->modules.entries) {
|
||||||
|
|||||||
@@ -1965,6 +1965,14 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case BuiltinProc___entry_point:
|
||||||
|
if (p->module->info->entry_point) {
|
||||||
|
lbValue entry_point = lb_find_procedure_value_from_entity(p->module, p->module->info->entry_point);
|
||||||
|
GB_ASSERT(entry_point.value != nullptr);
|
||||||
|
lb_emit_call(p, entry_point, {});
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
|
||||||
case BuiltinProc_syscall:
|
case BuiltinProc_syscall:
|
||||||
{
|
{
|
||||||
unsigned arg_count = cast(unsigned)ce->args.count;
|
unsigned arg_count = cast(unsigned)ce->args.count;
|
||||||
|
|||||||
Reference in New Issue
Block a user