This function:
# Generate the main C function.
#
# This function:
#
# * allocate the Sys object if it exists
# * call init if is exists
# * call main if it exists
fun compile_main_function
do
var v = self.new_visitor
v.add_decl("#include <signal.h>")
var platform = target_platform
var no_main = platform.no_main or modelbuilder.toolcontext.opt_no_main.value
if platform.supports_libunwind then
v.add_decl("#ifndef NO_STACKTRACE")
v.add_decl("#define UNW_LOCAL_ONLY")
v.add_decl("#include <libunwind.h>")
v.add_decl("#include \"c_functions_hash.h\"")
v.add_decl("#endif")
end
v.add_decl("int glob_argc;")
v.add_decl("char **glob_argv;")
v.add_decl("val *glob_sys;")
# Store catch stack in thread local storage
v.add_decl """
#if defined(TARGET_OS_IPHONE)
// Use pthread_key_create and others for iOS
#include <pthread.h>
static pthread_key_t catch_stack_key;
static pthread_once_t catch_stack_key_created = PTHREAD_ONCE_INIT;
static void create_catch_stack()
{
pthread_key_create(&catch_stack_key, NULL);
}
struct catch_stack_t *getCatchStack()
{
pthread_once(&catch_stack_key_created, &create_catch_stack);
struct catch_stack_t *data = pthread_getspecific(catch_stack_key);
if (data == NULL) {
data = malloc(sizeof(struct catch_stack_t));
data->cursor = -1;
data->currentSize = 0;
data->envs = NULL;
pthread_setspecific(catch_stack_key, data);
}
return data;
}
#else
// Use __thread when available
__thread struct catch_stack_t catchStack = {-1, 0, NULL};
struct catch_stack_t *getCatchStack()
{
return &catchStack;
}
#endif
"""
if self.modelbuilder.toolcontext.opt_typing_test_metrics.value then
for tag in count_type_test_tags do
v.add_decl("long count_type_test_resolved_{tag};")
v.add_decl("long count_type_test_unresolved_{tag};")
v.add_decl("long count_type_test_skipped_{tag};")
v.compiler.header.add_decl("extern long count_type_test_resolved_{tag};")
v.compiler.header.add_decl("extern long count_type_test_unresolved_{tag};")
v.compiler.header.add_decl("extern long count_type_test_skipped_{tag};")
end
end
if self.modelbuilder.toolcontext.opt_invocation_metrics.value then
v.add_decl("long count_invoke_by_tables;")
v.add_decl("long count_invoke_by_direct;")
v.add_decl("long count_invoke_by_inline;")
v.compiler.header.add_decl("extern long count_invoke_by_tables;")
v.compiler.header.add_decl("extern long count_invoke_by_direct;")
v.compiler.header.add_decl("extern long count_invoke_by_inline;")
end
if self.modelbuilder.toolcontext.opt_isset_checks_metrics.value then
v.add_decl("long count_attr_reads = 0;")
v.add_decl("long count_isset_checks = 0;")
v.compiler.header.add_decl("extern long count_attr_reads;")
v.compiler.header.add_decl("extern long count_isset_checks;")
end
v.add_decl("static void show_backtrace(void) \{")
if platform.supports_libunwind then
v.add_decl("#ifndef NO_STACKTRACE")
v.add_decl("char* opt = getenv(\"NIT_NO_STACK\");")
v.add_decl("unw_cursor_t cursor;")
v.add_decl("if(opt==NULL)\{")
v.add_decl("unw_context_t uc;")
v.add_decl("unw_word_t ip;")
v.add_decl("char* procname = malloc(sizeof(char) * 100);")
v.add_decl("unw_getcontext(&uc);")
v.add_decl("unw_init_local(&cursor, &uc);")
v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
v.add_decl("PRINT_ERROR(\"-- Stack Trace ------------------------------\\n\");")
v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
v.add_decl("while (unw_step(&cursor) > 0) \{")
v.add_decl(" unw_get_proc_name(&cursor, procname, 100, &ip);")
v.add_decl(" const char* recv = get_nit_name(procname, strlen(procname));")
v.add_decl(" if (recv != NULL)\{")
v.add_decl(" PRINT_ERROR(\"` %s\\n\", recv);")
v.add_decl(" \}else\{")
v.add_decl(" PRINT_ERROR(\"` %s\\n\", procname);")
v.add_decl(" \}")
v.add_decl("\}")
v.add_decl("PRINT_ERROR(\"-------------------------------------------------\\n\");")
v.add_decl("free(procname);")
v.add_decl("\}")
v.add_decl("#endif /* NO_STACKTRACE */")
end
v.add_decl("\}")
v.add_decl("void sig_handler(int signo)\{")
v.add_decl "#ifdef _WIN32"
v.add_decl "PRINT_ERROR(\"Caught signal : %s\\n\", signo);"
v.add_decl "#else"
v.add_decl("PRINT_ERROR(\"Caught signal : %s\\n\", strsignal(signo));")
v.add_decl "#endif"
v.add_decl("show_backtrace();")
# rethrows
v.add_decl("signal(signo, SIG_DFL);")
v.add_decl "#ifndef _WIN32"
v.add_decl("kill(getpid(), signo);")
v.add_decl "#endif"
v.add_decl("\}")
v.add_decl("void fatal_exit(int status) \{")
v.add_decl("show_backtrace();")
v.add_decl("exit(status);")
v.add_decl("\}")
compile_before_main(v)
if no_main then
v.add_decl("int nit_main(int argc, char** argv) \{")
else
v.add_decl("int main(int argc, char** argv) \{")
end
compile_begin_main(v)
v.add "#if !defined(__ANDROID__) && !defined(TARGET_OS_IPHONE)"
v.add("signal(SIGABRT, sig_handler);")
v.add("signal(SIGFPE, sig_handler);")
v.add("signal(SIGILL, sig_handler);")
v.add("signal(SIGINT, sig_handler);")
v.add("signal(SIGTERM, sig_handler);")
v.add("signal(SIGSEGV, sig_handler);")
v.add "#endif"
v.add "#ifndef _WIN32"
v.add("signal(SIGPIPE, SIG_IGN);")
v.add "#endif"
v.add("glob_argc = argc; glob_argv = argv;")
v.add("initialize_gc_option();")
v.add "initialize_nitni_global_refs();"
var main_type = mainmodule.sys_type
if main_type != null then
var mainmodule = v.compiler.mainmodule
var glob_sys = v.init_instance(main_type)
v.add("glob_sys = {glob_sys};")
var main_init = mainmodule.try_get_primitive_method("init", main_type.mclass)
if main_init != null then
v.send(main_init, [glob_sys])
end
var main_method = mainmodule.try_get_primitive_method("run", main_type.mclass) or else
mainmodule.try_get_primitive_method("main", main_type.mclass)
if main_method != null then
v.send(main_method, [glob_sys])
end
end
if self.modelbuilder.toolcontext.opt_typing_test_metrics.value then
v.add_decl("long count_type_test_resolved_total = 0;")
v.add_decl("long count_type_test_unresolved_total = 0;")
v.add_decl("long count_type_test_skipped_total = 0;")
v.add_decl("long count_type_test_total_total = 0;")
for tag in count_type_test_tags do
v.add_decl("long count_type_test_total_{tag};")
v.add("count_type_test_total_{tag} = count_type_test_resolved_{tag} + count_type_test_unresolved_{tag} + count_type_test_skipped_{tag};")
v.add("count_type_test_resolved_total += count_type_test_resolved_{tag};")
v.add("count_type_test_unresolved_total += count_type_test_unresolved_{tag};")
v.add("count_type_test_skipped_total += count_type_test_skipped_{tag};")
v.add("count_type_test_total_total += count_type_test_total_{tag};")
end
v.add("printf(\"# dynamic count_type_test: total %l\\n\");")
v.add("printf(\"\\tresolved\\tunresolved\\tskipped\\ttotal\\n\");")
var tags = count_type_test_tags.to_a
tags.add("total")
for tag in tags do
v.add("printf(\"{tag}\");")
v.add("printf(\"\\t%ld (%.2f%%)\", count_type_test_resolved_{tag}, 100.0*count_type_test_resolved_{tag}/count_type_test_total_total);")
v.add("printf(\"\\t%ld (%.2f%%)\", count_type_test_unresolved_{tag}, 100.0*count_type_test_unresolved_{tag}/count_type_test_total_total);")
v.add("printf(\"\\t%ld (%.2f%%)\", count_type_test_skipped_{tag}, 100.0*count_type_test_skipped_{tag}/count_type_test_total_total);")
v.add("printf(\"\\t%ld (%.2f%%)\\n\", count_type_test_total_{tag}, 100.0*count_type_test_total_{tag}/count_type_test_total_total);")
end
end
if self.modelbuilder.toolcontext.opt_invocation_metrics.value then
v.add_decl("long count_invoke_total;")
v.add("count_invoke_total = count_invoke_by_tables + count_invoke_by_direct + count_invoke_by_inline;")
v.add("printf(\"# dynamic count_invocation: total %ld\\n\", count_invoke_total);")
v.add("printf(\"by table: %ld (%.2f%%)\\n\", count_invoke_by_tables, 100.0*count_invoke_by_tables/count_invoke_total);")
v.add("printf(\"direct: %ld (%.2f%%)\\n\", count_invoke_by_direct, 100.0*count_invoke_by_direct/count_invoke_total);")
v.add("printf(\"inlined: %ld (%.2f%%)\\n\", count_invoke_by_inline, 100.0*count_invoke_by_inline/count_invoke_total);")
end
if self.modelbuilder.toolcontext.opt_isset_checks_metrics.value then
v.add("printf(\"# dynamic attribute reads: %ld\\n\", count_attr_reads);")
v.add("printf(\"# dynamic isset checks: %ld\\n\", count_isset_checks);")
end
v.add("return 0;")
v.add("\}")
for m in mainmodule.in_importation.greaters do
var f = "FILE_"+m.c_name
v.add "const char {f}[] = \"{m.location.file.filename.escape_to_c}\";"
provide_declaration(f, "extern const char {f}[];")
end
end
src/compiler/abstract_compiler.nit:891,2--1122,4