aboutsummaryrefslogtreecommitdiff
path: root/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler.c')
-rw-r--r--src/compiler.c81
1 files changed, 50 insertions, 31 deletions
diff --git a/src/compiler.c b/src/compiler.c
index e7b242b..1af9537 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -12,6 +12,8 @@
#include <limits.h>
#include <assert.h>
+static void amal_compiler_deinit(amal_compiler *self);
+
static usize strnlen(const char *str, usize max_length) {
usize len;
len = 0;
@@ -31,9 +33,7 @@ static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char
return_if_error(structdecl_init(struct_decl, &compiler->root_scope, &compiler->allocator));
return_if_error(scoped_allocator_alloc(&compiler->allocator, sizeof(LhsExpr), (void**)lhs_expr));
- return_if_error(lhsexpr_init(*lhs_expr, bool_true, bool_true, bool_true,
- create_buffer_view(name, strnlen(name, PATH_MAX)),
- &compiler->allocator));
+ lhsexpr_init(*lhs_expr, bool_true, bool_true, bool_true, create_buffer_view(name, strnlen(name, PATH_MAX)));
return_if_error(ast_create(&compiler->allocator, struct_decl, AST_STRUCT_DECL, &(*lhs_expr)->rhs_expr));
return_if_error(ast_create(&compiler->allocator, *lhs_expr, AST_LHS, &expr));
expr->resolve_data.type = *lhs_expr;
@@ -64,7 +64,7 @@ void amal_compiler_options_init(amal_compiler_options *self) {
self->num_threads = 0;
}
-int amal_compiler_init(amal_compiler *self, const amal_compiler_options *options) {
+static CHECK_RESULT int amal_compiler_init(amal_compiler *self, const amal_compiler_options *options, amal_program *program) {
int i;
self->usable_thread_count = options ? options->num_threads : 0;
@@ -72,19 +72,20 @@ int amal_compiler_init(amal_compiler *self, const amal_compiler_options *options
self->usable_thread_count = amal_get_usable_thread_count();
if(self->usable_thread_count == 0) {
amal_log_warning("Unable to get the number of threads available on the system, using 1 thread.");
- amal_log_warning("You can override the number of threads using by setting compiler option for number of thread to use.");
+ amal_log_warning("You can override the number of threads used by setting compiler option for number of thread to use.");
self->usable_thread_count = 1;
}
}
+ amal_log_info("Using %d threads", self->usable_thread_count);
am_memset(&self->allocator, 0, sizeof(self->allocator));
am_memset(&self->root_scope, 0, sizeof(self->root_scope));
if(options)
- am_memcpy(&self->options, options, sizeof(self->options));
+ self->options = *options;
else
- am_memset(&self->options, 0, sizeof(self->options));
+ amal_compiler_options_init(&self->options);
+ self->program = program;
self->started = bool_false;
- self->used = bool_false;
self->generic_work_object_index = 0;
amal_mutex_init(&self->mutex);
@@ -92,7 +93,7 @@ int amal_compiler_init(amal_compiler *self, const amal_compiler_options *options
cleanup_if_error(scope_init(&self->root_scope, NULL, &self->allocator));
cleanup_if_error(buffer_init(&self->parsers, &self->allocator));
cleanup_if_error(buffer_init(&self->queued_files, &self->allocator));
- cleanup_if_error(hash_map_init(&self->file_scopes, &self->allocator, sizeof(FileScopeReference*), hash_compare_string, amal_hash_string));
+ cleanup_if_error(hash_map_init(&self->file_scopes, &self->allocator, sizeof(FileScopeReference*), hash_map_compare_string, amal_hash_string));
cleanup_if_error(scoped_allocator_alloc(&self->allocator,
self->usable_thread_count * sizeof(ParserThreadData),
(void**)&self->threads));
@@ -102,25 +103,18 @@ int amal_compiler_init(amal_compiler *self, const amal_compiler_options *options
return AMAL_COMPILER_OK;
cleanup:
- ignore_result_int(amal_compiler_deinit(self));
+ amal_compiler_deinit(self);
return AMAL_COMPILER_ERR;
}
-int amal_compiler_deinit(amal_compiler *self) {
+void amal_compiler_deinit(amal_compiler *self) {
int i;
- int result;
- result = AMAL_COMPILER_OK;
-
for(i = 0; i < self->usable_thread_count; ++i) {
- int r;
- r = parser_thread_data_deinit(&self->threads[i]);
- if(r != 0)
- result = r;
+ parser_thread_data_deinit(&self->threads[i]);
}
amal_mutex_deinit(&self->mutex);
scoped_allocator_deinit(&self->allocator);
- return result;
}
typedef enum {
@@ -199,13 +193,19 @@ static void* thread_callback_parse_file(void *userdata) {
cleanup:
/*
- To stop all other parsers from working cleanly, we simply clear the file queue,
- and the other threads will stop when they are done with the file they are currently parsing.
+ To stop all other parsers from working cleanly, we simply clear the file queue,
+ and the other threads will stop when they are done with the file they are currently parsing.
*/
if(result != NULL) {
ignore_result_int(amal_mutex_lock(&compiler_parser_userdata.compiler->mutex, "thread_callback_parse_file"));
buffer_clear(&compiler_parser_userdata.compiler->queued_files);
}
+ /*
+ There can be a data race between writing to this and when this is read in @amal_compiler_load_file_join_threads.
+ This is intentional and it's ok, because the join_threads function checks against this status is guaranteed at this point
+ to not be a certain value that it checks for. Writing to an int is atomic.
+ TODO: Verify this is ok on all platforms.
+ */
compiler_parser_userdata.parser_thread_data->status = PARSER_THREAD_STATUS_IDLE;
amal_mutex_tryunlock(&compiler_parser_userdata.compiler->mutex);
return result;
@@ -215,6 +215,7 @@ static CHECK_RESULT int thread_resolve_ast(amal_compiler *compiler, Parser *pars
AstCompilerContext compiler_context;
int result;
compiler_context.compiler = compiler;
+ compiler_context.parser = parser;
compiler_context.scope = NULL;
result = setjmp(compiler_context.env);
if(result == 0) {
@@ -245,14 +246,15 @@ static CHECK_RESULT int thread_generate_bytecode(Parser *parser) {
BytecodeCompilerContext compiler_context;
int result;
- return_if_error(scoped_allocator_alloc(parser->allocator, sizeof(Bytecode), (void**)&compiler_context.bytecode));
- return_if_error(bytecode_init(compiler_context.bytecode, parser->allocator));
+ return_if_error(bytecode_init(&compiler_context.bytecode, parser->allocator));
compiler_context.parser = parser;
amal_log_debug("Generating bytecode for file: %.*s", parser->tokenizer.code_name.size, parser->tokenizer.code_name.data);
result = setjmp(compiler_context.env);
- if(result == 0)
+ if(result == 0) {
generate_bytecode_from_ssa(&compiler_context);
+ parser->bytecode = compiler_context.bytecode;
+ }
return result;
}
@@ -443,6 +445,17 @@ static CHECK_RESULT int amal_compiler_dispatch_generic(amal_compiler *self, Thre
return amal_compiler_load_file_join_threads(self);
}
+static CHECK_RESULT int amal_compiler_generate_program(amal_compiler *self) {
+ Parser **parser;
+ Parser **parser_end;
+ parser = buffer_begin(&self->parsers);
+ parser_end = buffer_end(&self->parsers);
+ for(; parser != parser_end; ++parser) {
+ return_if_error(amal_program_append_bytecode(self->program, &(*parser)->bytecode));
+ }
+ return 0;
+}
+
static CHECK_RESULT int try_create_file_scope(amal_compiler *compiler, const char *filepath, FileScopeReference **file_scope, bool *new_entry) {
int ret;
char *result_path;
@@ -472,12 +485,16 @@ static CHECK_RESULT int try_create_file_scope(amal_compiler *compiler, const cha
return ret;
}
-int amal_compiler_load_file(amal_compiler *self, const char *filepath) {
+int amal_compiler_load_file(amal_compiler_options *options, amal_program *program, const char *filepath) {
+ assert(program);
+ assert(filepath);
+ amal_compiler compiler;
FileScopeReference *file_scope;
- if(self->used)
- return AMAL_COMPILER_ERR;
- self->used = bool_true;
- return amal_compiler_internal_load_file(self, filepath, &file_scope);
+ int result;
+ return_if_error(amal_compiler_init(&compiler, options, program));
+ result = amal_compiler_internal_load_file(&compiler, filepath, &file_scope);
+ amal_compiler_deinit(&compiler);
+ return result;
}
int amal_compiler_internal_load_file(amal_compiler *self, const char *filepath, FileScopeReference **file_scope) {
@@ -510,8 +527,7 @@ int amal_compiler_internal_load_file(amal_compiler *self, const char *filepath,
return_if_error(amal_compiler_select_thread_for_work(self, thread_work_data, &parser_thread_data));
if(main_job) {
- /*doc(CompilerFlow)
- # Compiler flow
+ /*doc(Compiler flow)
(Tokenize&parse -> Resolve AST -> Generate SSA -> Generate bytecode) -> Generate program\
Each step except the last is done using multiple threads in parallel and the output of each step is used
in the next step. The last step is not done in parallel because the last step is combining all bytecode
@@ -535,6 +551,9 @@ int amal_compiler_internal_load_file(amal_compiler *self, const char *filepath,
assert(amal_compiler_check_all_threads_done(self));
amal_log_info("Finished generating bytecode");
+ return_if_error(amal_compiler_generate_program(self));
+ amal_log_info("Finished generating program");
+
return AMAL_COMPILER_OK;
}