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