aboutsummaryrefslogtreecommitdiff
path: root/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler.c')
-rw-r--r--src/compiler.c143
1 files changed, 112 insertions, 31 deletions
diff --git a/src/compiler.c b/src/compiler.c
index b8bca1c..e44ba6a 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -38,6 +38,7 @@ int amal_compiler_init(amal_compiler *self) {
am_memset(&self->allocator, 0, sizeof(self->allocator));
am_memset(&self->main_thread_allocator, 0, sizeof(self->main_thread_allocator));
self->started = bool_false;
+ self->resolve_ast_index = 0;
amal_mutex_init(&self->mutex);
return_if_error(scoped_allocator_init(&self->allocator));
@@ -80,7 +81,26 @@ typedef struct {
BufferView filepath;
} CompilerParserThreadUserData;
-static CHECK_RESULT int amal_compiler_load_first_this_thread(amal_compiler *self, BufferView filepath, ScopedAllocator *allocator) {
+typedef struct {
+ amal_compiler *compiler;
+ ParserThreadData *parser_thread_data;
+ Parser *parser;
+} CompilerAstResolverThreadUserData;
+
+typedef enum {
+ THREAD_WORK_PARSE,
+ THREAD_WORK_RESOLVE_AST
+} ThreadWorkType;
+
+typedef struct {
+ union {
+ BufferView filepath;
+ Parser *parser;
+ } value;
+ ThreadWorkType type;
+} ThreadWorkData;
+
+static CHECK_RESULT int amal_compiler_load_in_this_thread(amal_compiler *self, BufferView filepath, ScopedAllocator *allocator) {
Parser parser;
int result;
result = AMAL_COMPILER_ERR;
@@ -88,7 +108,7 @@ static CHECK_RESULT int amal_compiler_load_first_this_thread(amal_compiler *self
return_if_error(parser_init(&parser, self, allocator));
cleanup_if_error(parser_parse_file(&parser, filepath));
- cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_load_first_this_thread"));
+ cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_load_in_this_thread"));
cleanup_if_error(buffer_append(&self->parsers, &parser, sizeof(parser)));
result = AMAL_COMPILER_OK;
@@ -99,54 +119,92 @@ static CHECK_RESULT int amal_compiler_load_first_this_thread(amal_compiler *self
/* TODO: Handle errors (stop parsing in all other threads and report errors/warnings) */
static void* thread_callback_parse_file(void *userdata) {
- int _;
BufferView next_file;
CompilerParserThreadUserData compiler_parser_userdata;
- (void)_;
- next_file = create_buffer_view_null();
assert(!amal_thread_is_main());
am_memcpy(&compiler_parser_userdata, userdata, sizeof(compiler_parser_userdata));
am_free(userdata);
- cleanup_if_error(amal_compiler_load_first_this_thread(compiler_parser_userdata.compiler,
- compiler_parser_userdata.filepath,
- &compiler_parser_userdata.parser_thread_data->allocator));
- cleanup_if_error(amal_mutex_lock(&compiler_parser_userdata.compiler->mutex, "thread_callback_parse_file"));
- if(compiler_parser_userdata.compiler->queued_files.size > 0)
- _ = buffer_pop(&compiler_parser_userdata.compiler->queued_files, &next_file, sizeof(next_file));
+ next_file = compiler_parser_userdata.filepath;
+ for(;;) {
+ cleanup_if_error(amal_compiler_load_in_this_thread(compiler_parser_userdata.compiler,
+ next_file,
+ &compiler_parser_userdata.parser_thread_data->allocator));
+ cleanup_if_error(amal_mutex_lock(&compiler_parser_userdata.compiler->mutex, "thread_callback_parse_file"));
+ cleanup_if_error(buffer_pop(&compiler_parser_userdata.compiler->queued_files, &next_file, sizeof(next_file)));
+ amal_mutex_tryunlock(&compiler_parser_userdata.compiler->mutex);
+ }
cleanup:
- if(!next_file.data)
- compiler_parser_userdata.parser_thread_data->status = PARSER_THREAD_STATUS_IDLE;
+ compiler_parser_userdata.parser_thread_data->status = PARSER_THREAD_STATUS_IDLE;
amal_mutex_tryunlock(&compiler_parser_userdata.compiler->mutex);
- if(next_file.data) {
- _ = amal_compiler_load_first_this_thread(compiler_parser_userdata.compiler,
- next_file,
- &compiler_parser_userdata.parser_thread_data->allocator);
+ return NULL;
+}
+
+/* TODO: Handle errors (stop resolving ast in all other threads and report errors/warnings) */
+static void* thread_callback_resolve_ast(void *userdata) {
+ Parser *parser;
+ CompilerAstResolverThreadUserData compiler_ast_resolver_userdata;
+ assert(!amal_thread_is_main());
+
+ am_memcpy(&compiler_ast_resolver_userdata, userdata, sizeof(compiler_ast_resolver_userdata));
+ am_free(userdata);
+ parser = compiler_ast_resolver_userdata.parser;
+ for(;;) {
+ amal_log_debug("Resolving AST for file: %.*s", parser->tokenizer.code_name.size, parser->tokenizer.code_name.data);
+ scope_resolve(&parser->scope);
+ cleanup_if_error(amal_mutex_lock(&compiler_ast_resolver_userdata.compiler->mutex, "thread_callback_resolve_ast"));
+ if(compiler_ast_resolver_userdata.compiler->resolve_ast_index + 1 >= (int)buffer_get_size(&compiler_ast_resolver_userdata.compiler->parsers, Parser))
+ break;
+ ++compiler_ast_resolver_userdata.compiler->resolve_ast_index;
+ parser = buffer_get(&compiler_ast_resolver_userdata.compiler->parsers, compiler_ast_resolver_userdata.compiler->resolve_ast_index, sizeof(Parser));
+ amal_mutex_tryunlock(&compiler_ast_resolver_userdata.compiler->mutex);
}
+
+ cleanup:
+ compiler_ast_resolver_userdata.parser_thread_data->status = PARSER_THREAD_STATUS_IDLE;
+ amal_mutex_tryunlock(&compiler_ast_resolver_userdata.compiler->mutex);
return NULL;
}
-static CHECK_RESULT int amal_compiler_load_file_select_thread(amal_compiler *self, BufferView filepath, ParserThreadData **thread_selected) {
+static CHECK_RESULT int amal_compiler_select_thread_for_work(amal_compiler *self, ThreadWorkData work_data, ParserThreadData **thread_selected) {
int i;
int result;
ParserThreadData *parser_thread_data;
- CompilerParserThreadUserData *thread_user_data;
+ void *thread_user_data;
thread_user_data = NULL;
*thread_selected = NULL;
result = AMAL_COMPILER_ERR;
- cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_load_file_select_thread"));
+ cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_select_thread_for_work"));
for(i = 0; i < self->usable_thread_count; ++i) {
parser_thread_data = &self->threads[i];
if(parser_thread_data->status == PARSER_THREAD_STATUS_RUNNING)
continue;
- cleanup_if_error(am_malloc(sizeof(CompilerParserThreadUserData), (void**)&thread_user_data));
- thread_user_data->compiler = self;
- thread_user_data->parser_thread_data = parser_thread_data;
- thread_user_data->filepath = filepath;
- result = parser_thread_data_start(parser_thread_data, thread_callback_parse_file, thread_user_data);
+ switch(work_data.type) {
+ case THREAD_WORK_PARSE: {
+ CompilerParserThreadUserData *userdata;
+ cleanup_if_error(am_malloc(sizeof(CompilerParserThreadUserData), (void**)&userdata));
+ thread_user_data = userdata;
+ userdata->compiler = self;
+ userdata->parser_thread_data = parser_thread_data;
+ userdata->filepath = work_data.value.filepath;
+ result = parser_thread_data_start(parser_thread_data, thread_callback_parse_file, userdata);
+ break;
+ }
+ case THREAD_WORK_RESOLVE_AST: {
+ CompilerAstResolverThreadUserData *userdata;
+ cleanup_if_error(am_malloc(sizeof(CompilerAstResolverThreadUserData), (void**)&userdata));
+ thread_user_data = userdata;
+ userdata->compiler = self;
+ userdata->parser_thread_data = parser_thread_data;
+ userdata->parser = work_data.value.parser;
+ ++self->resolve_ast_index;
+ result = parser_thread_data_start(parser_thread_data, thread_callback_resolve_ast, userdata);
+ break;
+ }
+ }
*thread_selected = parser_thread_data;
break;
}
@@ -158,13 +216,13 @@ static CHECK_RESULT int amal_compiler_load_file_select_thread(amal_compiler *sel
return result;
}
-static CHECK_RESULT int amal_compiler_all_threads_done(amal_compiler *self, bool *done) {
+static CHECK_RESULT int amal_compiler_check_all_threads_done(amal_compiler *self, bool *done) {
int i;
int result;
result = AMAL_COMPILER_OK;
*done = bool_false;
- cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_all_threads_done"));
+ cleanup_if_error(amal_mutex_lock(&self->mutex, "amal_compiler_check_all_threads_done"));
for(i = 0; i < self->usable_thread_count; ++i) {
ParserThreadData *parser_thread_data;
parser_thread_data = &self->threads[i];
@@ -201,11 +259,10 @@ static CHECK_RESULT int amal_compiler_load_file_join_threads(amal_compiler *self
amal_mutex_tryunlock(&self->mutex);
if(result != 0)
goto cleanup;
- amal_log_debug("Joining thread %d, status %d", i, parser_thread_data->status);
ignore_result_int(parser_thread_data_join(parser_thread_data, &thread_return_data));
}
- cleanup_if_error(amal_compiler_all_threads_done(self, &done));
+ cleanup_if_error(amal_compiler_check_all_threads_done(self, &done));
if(done)
break;
}
@@ -215,12 +272,33 @@ static CHECK_RESULT int amal_compiler_load_file_join_threads(amal_compiler *self
return result;
}
+static CHECK_RESULT int amal_compiler_resolve_ast(amal_compiler *self) {
+ Parser *parser;
+ Parser *parser_end;
+ parser = buffer_start(&self->parsers);
+ parser_end = buffer_end(&self->parsers);
+ for(; parser != parser_end; ++parser) {
+ ParserThreadData *thread_selected;
+ ThreadWorkData thread_work_data;
+ thread_work_data.type = THREAD_WORK_RESOLVE_AST;
+ thread_work_data.value.parser = parser;
+ return_if_error(amal_compiler_select_thread_for_work(self, thread_work_data, &thread_selected));
+ /* After all threads have been used, they will handle using the remaining parsers */
+ if(!thread_selected)
+ break;
+ }
+ return amal_compiler_load_file_join_threads(self);
+}
+
int amal_compiler_load_file(amal_compiler *self, BufferView filepath) {
int result;
ParserThreadData *parser_thread_data;
+ ThreadWorkData thread_work_data;
result = AMAL_COMPILER_ERR;
+ thread_work_data.type = THREAD_WORK_PARSE;
+ thread_work_data.value.filepath = filepath;
- return_if_error(amal_compiler_load_file_select_thread(self, filepath, &parser_thread_data));
+ return_if_error(amal_compiler_select_thread_for_work(self, thread_work_data, &parser_thread_data));
/*
amal_compiler_load_file is called by the user for the first file to compile
@@ -230,7 +308,10 @@ int amal_compiler_load_file(amal_compiler *self, BufferView filepath) {
self->started = bool_true;
/*amal_log_info("Parsing %.*s using %d thread(s)", (int)filepath.size, filepath.data, self->usable_thread_count);*/
/*return_if_error(amal_compiler_load_first_this_thread(self, filepath, &self->main_thread_allocator));*/
- return amal_compiler_load_file_join_threads(self);
+ return_if_error(amal_compiler_load_file_join_threads(self));
+ amal_log_debug("Finished parsing all files, resolving AST");
+ return_if_error(amal_compiler_resolve_ast(self));
+ return AMAL_COMPILER_OK;
}
if(parser_thread_data)