aboutsummaryrefslogtreecommitdiff
path: root/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler.c')
-rw-r--r--src/compiler.c93
1 files changed, 73 insertions, 20 deletions
diff --git a/src/compiler.c b/src/compiler.c
index dbc1498..8dda1c6 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -25,13 +25,15 @@ static usize strnlen(const char *str, usize max_length) {
}
/* TODO: Allow to specify size and members? */
-static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char *name, amal_default_type **default_type) {
+static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char *name, u32 num_pointers, u32 fixed_size, amal_default_type **default_type) {
StructDecl *struct_decl;
Ast *expr;
LhsExpr *lhs_expr;
return_if_error(arena_allocator_alloc(&compiler->allocator, sizeof(StructDecl), (void**)&struct_decl));
return_if_error(structdecl_init(struct_decl, &compiler->root_scope, &compiler->allocator));
+ struct_decl->fields_num_pointers = num_pointers;
+ struct_decl->fields_fixed_size_bytes = fixed_size;
return_if_error(arena_allocator_alloc(&compiler->allocator, sizeof(amal_default_type), (void**)default_type));
lhs_expr = &(*default_type)->lhs_expr;
@@ -45,20 +47,29 @@ static CHECK_RESULT int create_default_type(amal_compiler *compiler, const char
return scope_add_child(&compiler->root_scope, expr);
}
+static CHECK_RESULT int create_default_type_num_pointers(amal_compiler *compiler, const char *name, u32 num_pointers, amal_default_type **default_type) {
+ return create_default_type(compiler, name, num_pointers, 0, default_type);
+}
+
+static CHECK_RESULT int create_default_type_fixed_size(amal_compiler *compiler, const char *name, u32 byte_size, amal_default_type **default_type) {
+ return create_default_type(compiler, name, 0, byte_size, default_type);
+}
+
static CHECK_RESULT int init_default_types(amal_compiler *compiler) {
- return_if_error(create_default_type(compiler, "i8", &compiler->default_types.i8));
- return_if_error(create_default_type(compiler, "i16", &compiler->default_types.i16));
- return_if_error(create_default_type(compiler, "i32", &compiler->default_types.i32));
- return_if_error(create_default_type(compiler, "i64", &compiler->default_types.i64));
- return_if_error(create_default_type(compiler, "u8", &compiler->default_types.u8));
- return_if_error(create_default_type(compiler, "u16", &compiler->default_types.u16));
- return_if_error(create_default_type(compiler, "u32", &compiler->default_types.u32));
- return_if_error(create_default_type(compiler, "u64", &compiler->default_types.u64));
- return_if_error(create_default_type(compiler, "isize", &compiler->default_types.isize));
- return_if_error(create_default_type(compiler, "usize", &compiler->default_types.usize));
- return_if_error(create_default_type(compiler, "f32", &compiler->default_types.f32));
- return_if_error(create_default_type(compiler, "f64", &compiler->default_types.f64));
- return_if_error(create_default_type(compiler, "str", &compiler->default_types.str));
+ return_if_error(create_default_type_fixed_size(compiler, "i8", 1, &compiler->default_types.i8));
+ return_if_error(create_default_type_fixed_size(compiler, "i16", 2, &compiler->default_types.i16));
+ return_if_error(create_default_type_fixed_size(compiler, "i32", 3, &compiler->default_types.i32));
+ return_if_error(create_default_type_fixed_size(compiler, "i64", 4, &compiler->default_types.i64));
+ return_if_error(create_default_type_fixed_size(compiler, "u8", 1, &compiler->default_types.u8));
+ return_if_error(create_default_type_fixed_size(compiler, "u16", 2, &compiler->default_types.u16));
+ return_if_error(create_default_type_fixed_size(compiler, "u32", 3, &compiler->default_types.u32));
+ return_if_error(create_default_type_fixed_size(compiler, "u64", 4, &compiler->default_types.u64));
+ return_if_error(create_default_type_num_pointers(compiler, "isize", 1, &compiler->default_types.isize));
+ return_if_error(create_default_type_num_pointers(compiler, "usize", 1, &compiler->default_types.usize));
+ return_if_error(create_default_type_fixed_size(compiler, "f32", 4, &compiler->default_types.f32));
+ return_if_error(create_default_type_fixed_size(compiler, "f64", 8, &compiler->default_types.f64));
+ /* TODO: str should be a struct with the fields @data (ptr) and @size (usize) */
+ return_if_error(create_default_type_num_pointers(compiler, "str", 1, &compiler->default_types.str));
compiler->default_types.arithmetic_types[0] = compiler->default_types.i8;
compiler->default_types.arithmetic_types[1] = compiler->default_types.u8;
@@ -185,6 +196,7 @@ static CHECK_RESULT int amal_compiler_load_in_this_thread(amal_compiler *compile
file_scope->parser = parser;
return_if_error(parser_parse_file(parser, filepath));
cleanup_if_error(amal_mutex_lock(&compiler->mutex, "amal_compiler_load_in_this_thread, add parser"));
+ parser->index = buffer_get_size(&compiler->parsers, Parser*);
cleanup_if_error(buffer_append(&compiler->parsers, &parser, sizeof(parser)));
amal_log_info("Finished parsing %.*s", filepath.size, filepath.data);
result = AMAL_COMPILER_OK;
@@ -224,6 +236,7 @@ static CHECK_RESULT int thread_generate_ssa(Parser *parser) {
return_if_error(arena_allocator_alloc(parser->allocator, sizeof(Ssa), (void**)&compiler_context.ssa));
return_if_error(ssa_init(compiler_context.ssa, parser));
compiler_context.compiler = parser->compiler;
+ compiler_context.import_index = 0;
parser->ssa = compiler_context.ssa;
amal_log_debug("Generating SSA for file: %.*s", parser->tokenizer.code_name.size, parser->tokenizer.code_name.data);
result = setjmp(compiler_context.env);
@@ -238,7 +251,8 @@ static CHECK_RESULT int thread_generate_bytecode(Parser *parser) {
BytecodeCompilerContext compiler_context;
int result;
- return_if_error(bytecode_init(&compiler_context.bytecode, parser->allocator));
+ return_if_error(arena_allocator_alloc(parser->allocator, sizeof(Bytecode), (void**)&compiler_context.bytecode));
+ 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);
@@ -320,14 +334,11 @@ static CHECK_RESULT int amal_compiler_dispatch_generic(amal_compiler *self, Thre
}
static CHECK_RESULT int amal_compiler_generate_program(amal_compiler *self) {
- /*
- TODO: Copying the bytecode to the program can be done using multiple threads.
- Use self->threads for that.
- */
+ /* TODO: Copying the bytecode to the program can be done using multiple threads */
Parser **parser = buffer_begin(&self->parsers);
Parser **parser_end = buffer_end(&self->parsers);
for(; parser != parser_end; ++parser) {
- return_if_error(amal_program_append_bytecode(self->program, &(*parser)->bytecode));
+ return_if_error(amal_program_append_bytecode(self->program, (*parser)->bytecode));
}
return 0;
}
@@ -419,6 +430,47 @@ static CHECK_RESULT int validate_main_func(FileScopeReference *main_file_scope,
return 0;
}
+static void amal_compiler_parsers_set_bytecode_offsets(amal_compiler *self) {
+ /* magic number + major version + minor version + patch version */
+ u32 offset = sizeof(u32) + sizeof(u8) + sizeof(u8) + sizeof(u8);
+ Parser **parser = buffer_begin(&self->parsers);
+ Parser **parser_end = buffer_end(&self->parsers);
+ for(; parser != parser_end; ++parser) {
+ (*parser)->bytecode->offset = offset;
+ offset += (*parser)->bytecode->data.size;
+ }
+}
+
+/* TODO: Parallelize this? */
+static void amal_compiler_update_import_references(amal_compiler *self) {
+ Parser **parser_start = buffer_begin(&self->parsers);
+ Parser **parser = parser_start;
+ Parser **parser_end = buffer_end(&self->parsers);
+ amal_compiler_parsers_set_bytecode_offsets(self);
+
+ for(; parser != parser_end; ++parser) {
+ u8 *import_start = (u8*)(*parser)->bytecode->data.data + (*parser)->bytecode->import_index;
+ u8 num_imports = *import_start;
+ /* TODO: Remove these kinds of offset with sizeof. They are prone to hard-to-find bugs after code change */
+ BytecodeHeaderImport *header_import = (BytecodeHeaderImport*)(import_start + sizeof(u8) + sizeof(u32));
+ BytecodeHeaderImport *header_import_end = header_import + num_imports;
+
+ /*
+ The first import is the file itself and it already has function index,
+ but the index is localized to the function itself, so we need to add the offset
+ to the file itself as well.
+ */
+ header_import->function_index += (*parser)->bytecode->offset;
+ header_import->extern_function_index += (*parser)->bytecode->offset;
+ ++header_import;
+ for(; header_import != header_import_end; ++header_import) {
+ Parser *imported_parser = *(parser_start + header_import->parser_index);
+ header_import->function_index = imported_parser->bytecode->offset + imported_parser->bytecode->funcs_index;
+ header_import->extern_function_index = imported_parser->bytecode->offset + imported_parser->bytecode->extern_funcs_index;
+ }
+ }
+}
+
int amal_compiler_internal_load_file(amal_compiler *self, const char *filepath, FileScopeReference **file_scope) {
ThreadWorkData thread_work_data;
bool main_job;
@@ -472,6 +524,7 @@ int amal_compiler_internal_load_file(amal_compiler *self, const char *filepath,
amal_log_info("Finished generating SSA");
return_if_error(amal_compiler_dispatch_generic(self, THREAD_WORK_GENERATE_BYTECODE));
+ amal_compiler_update_import_references(self);
amal_log_info("Finished generating bytecode");
return_if_error(amal_compiler_generate_program(self));