From 16aaaa19a3ef4220726007d3e644ced0c9e06513 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 9 Sep 2019 01:08:34 +0200 Subject: Allow referencing code in imported file (right now for function calls, allow calling a function in another file) --- src/compiler.c | 93 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 20 deletions(-) (limited to 'src/compiler.c') 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)); -- cgit v1.2.3