aboutsummaryrefslogtreecommitdiff
path: root/src/program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/program.c')
-rw-r--r--src/program.c225
1 files changed, 169 insertions, 56 deletions
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);