From 7d663615b2a44715e7447a40cae467d7d4e38b9c Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 14 Sep 2019 00:52:24 +0200 Subject: Start on opengl test, fix stack alignment before call (sys-v) --- src/program.c | 162 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 72 insertions(+), 90 deletions(-) (limited to 'src/program.c') diff --git a/src/program.c b/src/program.c index a0a2407..5c07c5d 100644 --- a/src/program.c +++ b/src/program.c @@ -42,7 +42,6 @@ static usize hash_u64(const u8 *data, usize size) { int amal_program_init(amal_program *self) { ignore_result_int(buffer_init(&self->data, NULL)); self->string_indices = NULL; - self->extern_func_indices = NULL; self->intermediates_start = NULL; self->strings_start = NULL; self->extern_funcs_start = NULL; @@ -72,15 +71,13 @@ int amal_program_init(amal_program *self) { void amal_program_deinit(amal_program *self) { arena_allocator_deinit(&self->allocator); - am_free(self->extern_func_indices); am_free(self->string_indices); - self->extern_func_indices = NULL; self->string_indices = NULL; if(self->data.data) buffer_deinit(&self->data); } -int amal_program_add_extern_func(amal_program *self, BufferView name, void *func_ptr, int args_byte_size) { +int amal_program_register_extern_func(amal_program *self, BufferView name, void *func_ptr, int args_byte_size) { ProgramExternFunc extern_func; extern_func.func = func_ptr; extern_func.args_byte_size = args_byte_size; @@ -93,44 +90,52 @@ int amal_program_add_extern_func(amal_program *self, BufferView name, void *func static u8* amal_program_get_extern_funcs_start_by_import_index(amal_program *self, u8 import_index) { BytecodeHeaderImport *header_import = (BytecodeHeaderImport*)self->imports_start; + u32 extern_function_index = 0; header_import += import_index; - return (u8*)self->data.data + header_import->extern_function_index; + assert(sizeof(extern_function_index) == sizeof(header_import->extern_function_index)); + am_memcpy(&extern_function_index, &header_import->extern_function_index, sizeof(extern_function_index)); + return (u8*)self->data.data + extern_function_index; +} + +static u32 extern_func_get_total_param_size(BytecodeHeaderExternFunction *self) { + return self->params_fixed_size + self->params_num_pointers * sizeof(void*); } typedef struct { - u8 num_params; + BytecodeHeaderExternFunction extern_func; BufferView name; -} BytecodeHeaderExternFunction; +} BytecodeHeaderExternFunctionFull; /* TODO: Optimize this */ -static void amal_program_get_header_extern_function_by_index(amal_program *self, u8 import_index, u16 index, BytecodeHeaderExternFunction *result) { +static void amal_program_get_header_extern_function_by_index(amal_program *self, u8 import_index, u16 index, BytecodeHeaderExternFunctionFull *result) { u32 i; u8 *extern_funcs_start = amal_program_get_extern_funcs_start_by_import_index(self, import_index); extern_funcs_start += sizeof(u16) + sizeof(u32); for(i = 0; i < (u32)index; ++i) { - u8 name_len = *(extern_funcs_start + sizeof(u8)); - /* +1 for the null-terminated character */ - extern_funcs_start += sizeof(u8) + sizeof(u8) + name_len + 1; + u8 name_len; + extern_funcs_start += sizeof(BytecodeHeaderExternFunction); + name_len = *extern_funcs_start; + extern_funcs_start += 1 + name_len + 1; /* +1 for skipping length byte and the null-terminated character */ } - result->num_params = extern_funcs_start[0]; - result->name.size = extern_funcs_start[1]; - result->name.data = (const char*)extern_funcs_start + sizeof(u8) + sizeof(u8); + am_memcpy(&result->extern_func, extern_funcs_start, sizeof(result->extern_func)); + result->name.size = *(extern_funcs_start + sizeof(result->extern_func)); + result->name.data = (const char*)extern_funcs_start + sizeof(result->extern_func) + sizeof(u8); } static CHECK_RESULT int amal_program_get_extern_func_by_index(amal_program *self, u8 import_index, u16 index, ProgramExternFunc *result) { - BytecodeHeaderExternFunction extern_func; + BytecodeHeaderExternFunctionFull extern_func; amal_program_get_header_extern_function_by_index(self, import_index, index, &extern_func); if(!hash_map_get(&self->extern_funcs_map, extern_func.name, result)) { - amal_log_error("No such extern function: %.*s", extern_func.name.size, extern_func.name.data); + amal_log_error("Extern function \"%.*s\" has not been registered", extern_func.name.size, extern_func.name.data); return AMAL_PROGRAM_NO_SUCH_EXTERNAL_FUNCTION; } /* TODO: This assumes all arguments are of size sizeof(isize) */ - if(result->args_byte_size != -1 && result->args_byte_size != extern_func.num_params * (int)sizeof(isize)) { + if(result->args_byte_size != -1 && result->args_byte_size != (int)extern_func_get_total_param_size(&extern_func.extern_func)) { amal_log_error("Extern function %.*s was registered to take %d byte(s), but the program says it takes %d byte(s)", - extern_func.name.size, extern_func.name.data, result->args_byte_size, extern_func.num_params * sizeof(isize)); + extern_func.name.size, extern_func.name.data, result->args_byte_size, (int)extern_func_get_total_param_size(&extern_func.extern_func)); return AMAL_PROGRAM_NO_SUCH_EXTERNAL_FUNCTION; } return 0; @@ -234,9 +239,6 @@ static CHECK_RESULT int amal_program_advance_section_magic_number(amal_program * static CHECK_RESULT int amal_program_read_intermediates(amal_program *self) { u32 intermediates_size; - /*u32 read_end;*/ - - return_if_error(amal_program_advance_section_magic_number(self)); if(bytes_left_to_read(self) < sizeof(intermediates_size)) { amal_log_error("Not enough space in program to intermediates size"); @@ -262,8 +264,6 @@ static CHECK_RESULT int amal_program_read_strings(amal_program *self) { u32 strings_size; u32 *string_index_ptr; - return_if_error(amal_program_advance_section_magic_number(self)); - if(!amal_program_read_advance(self, &self->num_strings, sizeof(u16))) return AMAL_PROGRAM_INVALID_STRINGS; @@ -309,8 +309,6 @@ static CHECK_RESULT int amal_program_read_strings(amal_program *self) { static CHECK_RESULT int amal_program_read_functions(amal_program *self) { u32 funcs_size; - return_if_error(amal_program_advance_section_magic_number(self)); - if(!amal_program_read_advance(self, &self->num_functions, sizeof(u16))) return AMAL_PROGRAM_INVALID_FUNCTIONS; @@ -324,9 +322,6 @@ static CHECK_RESULT int amal_program_read_functions(amal_program *self) { static CHECK_RESULT int amal_program_read_external_functions(amal_program *self) { u32 extern_funcs_size; - u32 *extern_func_index_ptr; - - return_if_error(amal_program_advance_section_magic_number(self)); if(!amal_program_read_advance(self, &self->num_extern_functions, sizeof(u16))) return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; @@ -337,46 +332,13 @@ static CHECK_RESULT int amal_program_read_external_functions(amal_program *self) if(bytes_left_to_read(self) < extern_funcs_size) return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS_SIZE; - am_free(self->extern_func_indices); - self->extern_func_indices = NULL; - if(am_malloc(sizeof(u32) * self->num_extern_functions, (void**)&self->extern_func_indices) != 0) - return AMAL_PROGRAM_ALLOC_FAILURE; - extern_func_index_ptr = self->extern_func_indices; - - { - const u32 read_start = self->read_index; - const u32 read_end = read_start + extern_funcs_size; - self->extern_funcs_start = (u8*)(self->data.data + self->read_index); - while(self->read_index < read_end) { - u8 num_params; - u8 func_name_size; - - if(bytes_left_to_read(self) < sizeof(num_params) + sizeof(func_name_size)) - return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; - - *extern_func_index_ptr = self->read_index - read_start; - ++extern_func_index_ptr; - num_params = self->data.data[self->read_index]; - func_name_size = self->data.data[self->read_index + sizeof(num_params)]; - self->read_index += sizeof(num_params) + sizeof(func_name_size); - - /* +1 to skip null-termination character */ - if(bytes_left_to_read(self) < func_name_size + 1U) - return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; - - self->read_index += func_name_size + 1; /* +1 to skip null-termination character */ - } - assert(self->read_index == read_end); - } - + self->read_index += extern_funcs_size; return AMAL_PROGRAM_OK; } static CHECK_RESULT int amal_program_read_exported_functions(amal_program *self) { u32 export_funcs_size; - return_if_error(amal_program_advance_section_magic_number(self)); - if(!amal_program_read_advance(self, &self->num_exported_functions, sizeof(u16))) return AMAL_PROGRAM_INVALID_EXPORTED_FUNCTIONS; @@ -399,8 +361,6 @@ static CHECK_RESULT int amal_program_read_exported_functions(amal_program *self) static CHECK_RESULT int amal_program_read_imports(amal_program *self) { u32 imports_size; - return_if_error(amal_program_advance_section_magic_number(self)); - if(!amal_program_read_advance(self, &self->num_imports, sizeof(u8))) return AMAL_PROGRAM_INVALID_IMPORTS; @@ -437,20 +397,26 @@ static CHECK_RESULT int amal_program_get_data_by_index(amal_program *self, u16 i static u8* amal_program_get_funcs_start_by_import_index(amal_program *self, u8 import_index) { BytecodeHeaderImport *header_import = (BytecodeHeaderImport*)self->imports_start; + u32 function_index = 0; header_import += import_index; - return (u8*)self->data.data + header_import->function_index; + assert(sizeof(function_index) == sizeof(header_import->function_index)); + am_memcpy(&function_index, &header_import->function_index, sizeof(function_index)); + return (u8*)self->data.data + function_index; } -static BytecodeHeaderFunction* amal_program_get_header_function_by_index(amal_program *self, u8 import_index, u16 index) { +static void amal_program_get_header_function_by_index(amal_program *self, u8 import_index, u16 index, BytecodeHeaderFunction *result) { u8 *funcs_start = amal_program_get_funcs_start_by_import_index(self, import_index); BytecodeHeaderFunction *header_func = (BytecodeHeaderFunction*)(funcs_start + sizeof(u16) + sizeof(u32)); - return header_func + index; + am_memcpy(result, header_func + index, sizeof(BytecodeHeaderFunction)); } static u64 deferred_func_call_get_key(amal_program *self, u8 import_index, u16 func_index) { BytecodeHeaderImport *header_import = (BytecodeHeaderImport*)self->imports_start; + u32 function_index = 0; header_import += import_index; - return ((u64)func_index << 32) | (u64)header_import->function_index; + assert(sizeof(function_index) == sizeof(header_import->function_index)); + am_memcpy(&function_index, &header_import->function_index, sizeof(function_index)); + return ((u64)func_index << 32) | (u64)function_index; } static CHECK_RESULT int resolve_deferred_func_calls(amal_program *self, amal_executor *executor, u16 func_index) { @@ -474,7 +440,8 @@ static CHECK_RESULT int resolve_deferred_func_calls(amal_program *self, amal_exe static void header_func_set_offset(amal_program *self, u16 func_index, u32 code_offset) { BytecodeHeaderFunction *header_func = ((BytecodeHeaderFunction*)self->funcs_start) + func_index; - header_func->func_offset = code_offset; + assert(sizeof(header_func->func_offset) == sizeof(code_offset)); + am_memcpy(&header_func->func_offset, &code_offset, sizeof(code_offset)); } static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_executor *executor) { @@ -489,8 +456,6 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ func_counter = 0; self->return_value_index = 0; - return_if_error(amal_program_advance_section_magic_number(self)); - if(!amal_program_read_advance(self, &instructions_size, sizeof(instructions_size))) return AMAL_PROGRAM_INVALID_INSTRUCTIONS_SIZE; @@ -614,20 +579,22 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u8 import_index; u16 func_index; u8 num_args; - BytecodeHeaderFunction *func_def; + BytecodeHeaderFunction func_def; i8 dst_reg; am_memcpy(&import_index, self->data.data + self->read_index, sizeof(import_index)); am_memcpy(&func_index, self->data.data + self->read_index + sizeof(import_index), sizeof(func_index)); am_memcpy(&num_args, self->data.data + self->read_index + sizeof(import_index) + sizeof(func_index), sizeof(num_args)); - func_def = amal_program_get_header_function_by_index(self, import_index, func_index); - assert(func_def->num_return_types == 1 && "TODO: Support 0 and more than 1 return values"); + amal_program_get_header_function_by_index(self, import_index, func_index, &func_def); + assert(func_def.num_return_types == 1 && "TODO: Support 0 and more than 1 return values"); assert(self->return_value_index == 1); dst_reg = self->return_values_stack[0]; - self->return_value_index -= func_def->num_return_types; + self->return_value_index -= func_def.num_return_types; - if((char*)func_def < self->data.data + self->read_index) { - return_if_error(amal_exec_call(executor, func_def->func_offset, num_args, dst_reg)); + /* func_offset will only be non-zero when the function has been decoded (FUNC_START) */ + if(func_def.func_offset != 0) { + /* TODO: Instead of pushing num args, push the sum of sizeof the last num_args */ + return_if_error(amal_exec_call(executor, func_def.func_offset, num_args, dst_reg)); } else { /* The code for the function has not been generated yet (the function is defined after the current location). @@ -746,6 +713,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ int amal_program_run(amal_program *self) { int result; amal_executor *executor; + if(self->data.size > PROGRAM_MAX_SIZE) { amal_log_error("Program is too large. Max size is 1GB"); return AMAL_PROGRAM_ERR; @@ -755,12 +723,25 @@ int amal_program_run(amal_program *self) { cleanup_if_error(amal_program_read_header(self)); while(bytes_left_to_read(self) > 0) { + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_intermediates(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_strings(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_functions(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_external_functions(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_exported_functions(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_imports(self)); + + cleanup_if_error(amal_program_advance_section_magic_number(self)); cleanup_if_error(amal_program_read_instructions(self, executor)); } if(self->main_func_instruction_offset == ~(u32)0U) { @@ -776,21 +757,22 @@ int amal_program_run(amal_program *self) { } int amal_program_save(amal_program *self, const char *filepath) { - FILE *file; - file = fopen(filepath, "wb"); + int err = 0; + FILE *file = fopen(filepath, "wb"); if(!file) { - int err; - err = errno; - perror(filepath); - return -err; + err = -errno; + goto cleanup; } + if(fwrite(self->data.data, 1, self->data.size, file) != self->data.size) { - int err; - err = errno; - perror(filepath); - return -err; + err = -errno; + goto cleanup; } - fclose(file); - return 0; -} + cleanup: + if(err != 0) + perror(filepath); + if(file) + fclose(file); + return err; +} -- cgit v1.2.3