From c1bea102df3f2907f345b89ff0f66f5055ac4767 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 18 Aug 2019 06:25:52 +0200 Subject: Add extern funcs, parameter registers, fix asm_rm RSP bug --- src/program.c | 225 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 169 insertions(+), 56 deletions(-) (limited to 'src/program.c') diff --git a/src/program.c b/src/program.c index a73cf72..9ec1b41 100644 --- a/src/program.c +++ b/src/program.c @@ -1,5 +1,6 @@ #include "../include/program.h" #include "../include/std/mem.h" +#include "../include/std/hash.h" #include "../include/std/alloc.h" #include "../include/std/log.h" #include "../include/std/buffer_view.h" @@ -26,7 +27,7 @@ typedef struct { } Number; /*doc(Bytecode) -The layout of the full bytecode is: Header (Intermediates Strings Functions Instructions)* +The layout of the full bytecode is: Header (Intermediates Strings Functions External_Functions Instructions)* */ static CHECK_RESULT int amal_program_append_header(amal_program *self) { @@ -58,13 +59,18 @@ static CHECK_RESULT int amal_program_append_header(amal_program *self) { 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; self->read_index = 0; self->num_intermediates = 0; self->num_strings = 0; self->num_functions = 0; + self->num_extern_functions = 0; + cleanup_if_error(arena_allocator_init(&self->allocator)); + cleanup_if_error(hash_map_init(&self->extern_funcs_map, &self->allocator, sizeof(ProgramExternFunc), hash_map_compare_string, amal_hash_string)); cleanup_if_error(amal_program_append_header(self)); return 0; @@ -74,9 +80,51 @@ int amal_program_init(amal_program *self) { } void amal_program_deinit(amal_program *self) { - buffer_deinit(&self->data); + arena_allocator_deinit(&self->allocator); + am_free(self->extern_func_indices); am_free(self->string_indices); - 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) { + ProgramExternFunc extern_func; + extern_func.func = func_ptr; + extern_func.args_byte_size = args_byte_size; + return hash_map_insert(&self->extern_funcs_map, name, &extern_func); +} + +static CHECK_RESULT int amal_program_get_extern_func_by_index(amal_program *self, u16 index, ProgramExternFunc *result) { + u8 *extern_func_ptr; + u8 num_args; + u8 func_name_len; + BufferView func_name; + + if(index >= self->num_extern_functions) { + result->func = NULL; + result->args_byte_size = 0; + amal_log_error("Extern func index index %ld is out of range (%ld)", index, self->num_extern_functions); + return AMAL_PROGRAM_INSTRUCTION_INVALID_EXTERN_FUNC_INDEX; + } + + extern_func_ptr = self->extern_funcs_start + self->extern_func_indices[index]; + + am_memcpy(&num_args, extern_func_ptr, sizeof(num_args)); + am_memcpy(&func_name_len, extern_func_ptr + sizeof(num_args), sizeof(func_name_len)); + func_name.size = func_name_len; + func_name.data = (const char*)(extern_func_ptr + sizeof(num_args) + sizeof(func_name_len)); + + if(!hash_map_get(&self->extern_funcs_map, func_name, result)) { + amal_log_error("No such extern function: %.*s", func_name.size, 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 != num_args * (int)sizeof(isize)) { + amal_log_error("Extern function %.*s was registered to take %d byte(s), but the program says it takes %d byte(s)", func_name.size, func_name.data, result->args_byte_size, num_args * sizeof(isize)); + return AMAL_PROGRAM_NO_SUCH_EXTERNAL_FUNCTION; + } + return 0; } int amal_program_append_bytecode(amal_program *self, Bytecode *bytecode) { @@ -119,6 +167,14 @@ static CHECK_RESULT int amal_program_read_header(amal_program *self) { return AMAL_PROGRAM_OK; } +static CHECK_RESULT bool amal_program_read_advance(amal_program *self, void *output, usize bytes_to_read) { + if(bytes_left_to_read(self) < bytes_to_read) + return bool_false; + am_memcpy(output, self->data.data + self->read_index, bytes_to_read); + self->read_index += bytes_to_read; + return bool_true; +} + static CHECK_RESULT int amal_program_read_intermediates(amal_program *self) { u32 intermediates_size; /*u32 read_end;*/ @@ -136,7 +192,7 @@ static CHECK_RESULT int amal_program_read_intermediates(amal_program *self) { return AMAL_PROGRAM_INVALID_INTERMEDIATES_SIZE; } - self->intermediates_start = &self->data.data[self->read_index]; + self->intermediates_start = (u8*)(self->data.data + self->read_index); self->num_intermediates = intermediates_size / (sizeof(u8) + sizeof(u64)); self->read_index += intermediates_size; @@ -144,61 +200,98 @@ static CHECK_RESULT int amal_program_read_intermediates(amal_program *self) { } static CHECK_RESULT int amal_program_read_strings(amal_program *self) { - u16 num_strings; u32 strings_size; - u32 read_start; - u32 read_end; u32 *string_index_ptr; - if(bytes_left_to_read(self) < sizeof(num_strings)) + if(!amal_program_read_advance(self, &self->num_strings, sizeof(u16))) return AMAL_PROGRAM_INVALID_STRINGS; - am_memcpy(&num_strings, &self->data.data[self->read_index], sizeof(num_strings)); - self->read_index += sizeof(num_strings); - self->num_strings = num_strings; - - if(am_malloc(sizeof(u32) * num_strings, (void**)&self->string_indices) != 0) - return AMAL_PROGRAM_STRING_ALLOC_FAILURE; - string_index_ptr = self->string_indices; - - if(bytes_left_to_read(self) < sizeof(strings_size)) + if(!amal_program_read_advance(self, &strings_size, sizeof(strings_size))) return AMAL_PROGRAM_INVALID_STRINGS; - am_memcpy(&strings_size, &self->data.data[self->read_index], sizeof(strings_size)); - self->read_index += sizeof(strings_size); - if(bytes_left_to_read(self) < strings_size) return AMAL_PROGRAM_INVALID_STRINGS_SIZE; - read_start = self->read_index; - read_end = read_start + strings_size; - self->strings_start = &self->data.data[self->read_index]; - while(self->read_index < read_end) { - u16 string_size; + if(am_malloc(sizeof(u32) * self->num_strings, (void**)&self->string_indices) != 0) + return AMAL_PROGRAM_ALLOC_FAILURE; + string_index_ptr = self->string_indices; + + { + const u32 read_start = self->read_index; + const u32 read_end = read_start + strings_size; + self->strings_start = (u8*)(self->data.data + self->read_index); + while(self->read_index < read_end) { + u16 string_size; - if(bytes_left_to_read(self) < sizeof(string_size)) - return AMAL_PROGRAM_INVALID_STRINGS; + if(bytes_left_to_read(self) < sizeof(string_size)) + return AMAL_PROGRAM_INVALID_STRINGS; - *string_index_ptr = self->read_index - read_start; - ++string_index_ptr; - am_memcpy(&string_size, &self->data.data[self->read_index], sizeof(string_size)); - self->read_index += sizeof(string_size); + *string_index_ptr = self->read_index - read_start; + ++string_index_ptr; + am_memcpy(&string_size, &self->data.data[self->read_index], sizeof(string_size)); + self->read_index += sizeof(string_size); - if(bytes_left_to_read(self) < string_size) - return AMAL_PROGRAM_INVALID_STRINGS; + /* +1 to skip null-termination character */ + if(bytes_left_to_read(self) < string_size + 1U) + return AMAL_PROGRAM_INVALID_STRINGS; - self->read_index += string_size + 1; /* +1 to skip null-termination character */ + self->read_index += string_size + 1; /* +1 to skip null-termination character */ + } + assert(self->read_index == read_end); } - assert(self->read_index == read_end); return AMAL_PROGRAM_OK; } static CHECK_RESULT int amal_program_read_functions(amal_program *self) { - if(bytes_left_to_read(self) < sizeof(u16)) + if(!amal_program_read_advance(self, &self->num_functions, sizeof(u16))) return AMAL_PROGRAM_INVALID_FUNCTIONS; - am_memcpy(&self->num_functions, &self->data.data[self->read_index], sizeof(u16)); - self->read_index += sizeof(u16); + return AMAL_PROGRAM_OK; +} + +static CHECK_RESULT int amal_program_read_external_functions(amal_program *self) { + u32 extern_funcs_size; + u32 *extern_func_index_ptr; + + if(!amal_program_read_advance(self, &self->num_extern_functions, sizeof(u16))) + return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; + + if(!amal_program_read_advance(self, &extern_funcs_size, sizeof(extern_funcs_size))) + return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; + + if(bytes_left_to_read(self) < extern_funcs_size) + return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS_SIZE; + + 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_args; + u8 func_name_size; + + if(bytes_left_to_read(self) < sizeof(num_args) + sizeof(func_name_size)) + return AMAL_PROGRAM_INVALID_EXTERNAL_FUNCTIONS; + + *extern_func_index_ptr = self->read_index - read_start; + ++extern_func_index_ptr; + num_args = self->data.data[self->read_index]; + func_name_size = self->data.data[self->read_index + sizeof(num_args)]; + self->read_index += sizeof(num_args) + sizeof(func_name_size); + + /* +1 to skip null-termination character */ + if(bytes_left_to_read(self) < func_name_size + 1U) + return AMAL_PROGRAM_INVALID_STRINGS; + + self->read_index += func_name_size + 1; /* +1 to skip null-termination character */ + } + assert(self->read_index == read_end); + } + return AMAL_PROGRAM_OK; } @@ -212,7 +305,7 @@ static CHECK_RESULT int amal_program_get_intermediate_by_index(amal_program *sel } static CHECK_RESULT int amal_program_get_data_by_index(amal_program *self, u16 index, BufferView *result) { - char *str_ptr; + u8 *str_ptr; if(index >= self->num_strings) { amal_log_error("Data index %ld is out of range (%ld)", index, self->num_strings); @@ -221,7 +314,7 @@ static CHECK_RESULT int amal_program_get_data_by_index(amal_program *self, u16 i str_ptr = self->strings_start + self->string_indices[index]; am_memcpy(&result->size, str_ptr, sizeof(u16)); - result->data = str_ptr + sizeof(u16); + result->data = (const char*)(str_ptr + sizeof(u16)); return 0; } @@ -236,12 +329,9 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ (void)inside_func; func_counter = 0; - if(bytes_left_to_read(self) < sizeof(instructions_size)) + if(!amal_program_read_advance(self, &instructions_size, sizeof(instructions_size))) return AMAL_PROGRAM_INVALID_INSTRUCTIONS_SIZE; - am_memcpy(&instructions_size, &self->data.data[self->read_index], sizeof(instructions_size)); - self->read_index += sizeof(instructions_size); - if(bytes_left_to_read(self) < instructions_size) return AMAL_PROGRAM_INVALID_INSTRUCTIONS_SIZE; @@ -278,7 +368,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u16 intermediate_index; Number number; - am_memcpy(&intermediate_index, &self->data.data[self->read_index + sizeof(u8)], sizeof(intermediate_index)); + am_memcpy(&intermediate_index, &self->data.data[self->read_index + sizeof(i8)], sizeof(intermediate_index)); return_if_error(amal_program_get_intermediate_by_index(self, intermediate_index, &number)); return_if_error(amal_exec_movi(executor, self->data.data[self->read_index], number.value.integer)); @@ -289,7 +379,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ u16 data_index; BufferView data_ptr; - am_memcpy(&data_index, &self->data.data[self->read_index + sizeof(u8)], sizeof(data_index)); + am_memcpy(&data_index, &self->data.data[self->read_index + sizeof(i8)], sizeof(data_index)); return_if_error(amal_program_get_data_by_index(self, data_index, &data_ptr)); return_if_error(amal_exec_movd(executor, self->data.data[self->read_index], data_ptr)); @@ -355,16 +445,34 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ case AMAL_OP_CALL: { u16 func_index; u8 num_args; + i8 dst_reg; am_memcpy(&func_index, self->data.data + self->read_index, sizeof(func_index)); - am_memcpy(&num_args, self->data.data + self->read_index + sizeof(func_index), sizeof(num_args)); - return_if_error(amal_exec_call(executor, func_index, num_args)); - self->read_index += 3; + num_args = self->data.data[self->read_index + sizeof(func_index)]; + dst_reg = self->data.data[self->read_index + sizeof(func_index) + sizeof(num_args)]; + return_if_error(amal_exec_call(executor, func_index, num_args, dst_reg)); + self->read_index += 4; break; } case AMAL_OP_CALLR: assert(bool_false && "TODO: Implement CALLR"); self->read_index += 2; break; + case AMAL_OP_CALLE: { + u16 extern_func_index; + u8 num_args; + i8 dst_reg; + am_memcpy(&extern_func_index, self->data.data + self->read_index, sizeof(extern_func_index)); + num_args = self->data.data[self->read_index + sizeof(extern_func_index)]; + dst_reg = self->data.data[self->read_index + sizeof(extern_func_index) + sizeof(num_args)]; + + { + ProgramExternFunc extern_func; + return_if_error(amal_program_get_extern_func_by_index(self, extern_func_index, &extern_func)); + return_if_error(amal_exec_calle(executor, extern_func.func, num_args, dst_reg)); + } + self->read_index += 4; + break; + } case AMAL_OP_CMP: { return_if_error(amal_exec_cmp(executor, self->data.data[self->read_index], self->data.data[self->read_index + 1], self->data.data[self->read_index + 2])); self->read_index += 3; @@ -372,7 +480,7 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ } case AMAL_OP_JZ: { i16 jump_offset; - am_memcpy(&jump_offset, &self->data.data[self->read_index + sizeof(u8)], sizeof(jump_offset)); + am_memcpy(&jump_offset, &self->data.data[self->read_index + sizeof(i8)], sizeof(jump_offset)); return_if_error(amal_exec_jz(executor, self->data.data[self->read_index], jump_offset)); self->read_index += 3; break; @@ -385,21 +493,25 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_ break; } case AMAL_OP_RET: { - const u8 reg = self->data.data[self->read_index]; + const i8 reg = self->data.data[self->read_index]; return_if_error(amal_exec_ret(executor, reg)); self->read_index += 1; break; } case AMAL_OP_FUNC_START: { - u16 func_num_registers; + u8 func_num_param_regs; + u16 func_num_local_var_regs; + assert(!inside_func); inside_func = bool_true; assert(func_counter < self->num_functions); ++func_counter; - am_memcpy(&func_num_registers, &self->data.data[self->read_index], sizeof(func_num_registers)); - return_if_error(amal_exec_func_start(executor, func_num_registers)); - self->read_index += 2; + func_num_param_regs = self->data.data[self->read_index]; + (void)func_num_param_regs; + am_memcpy(&func_num_local_var_regs, self->data.data + self->read_index + sizeof(func_num_param_regs), sizeof(func_num_local_var_regs)); + return_if_error(amal_exec_func_start(executor, func_num_local_var_regs)); + self->read_index += 3; break; } case AMAL_OP_FUNC_END: { @@ -420,7 +532,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; - result = 0; + result = AMAL_PROGRAM_ERR; return_if_error(amal_executor_init(&executor)); cleanup_if_error(amal_program_read_header(self)); @@ -428,6 +540,7 @@ int amal_program_run(amal_program *self) { cleanup_if_error(amal_program_read_intermediates(self)); cleanup_if_error(amal_program_read_strings(self)); cleanup_if_error(amal_program_read_functions(self)); + cleanup_if_error(amal_program_read_external_functions(self)); cleanup_if_error(amal_program_read_instructions(self, executor)); } result = amal_executor_run(executor); -- cgit v1.2.3