aboutsummaryrefslogtreecommitdiff
path: root/src/program.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/program.c')
-rw-r--r--src/program.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/src/program.c b/src/program.c
index 54709b1..a73cf72 100644
--- a/src/program.c
+++ b/src/program.c
@@ -25,6 +25,10 @@ typedef struct {
NumberUnion value;
} Number;
+/*doc(Bytecode)
+The layout of the full bytecode is: Header (Intermediates Strings Functions Instructions)*
+*/
+
static CHECK_RESULT int amal_program_append_header(amal_program *self) {
/*doc(Bytecode header)
# Header layout
@@ -57,8 +61,9 @@ int amal_program_init(amal_program *self) {
self->intermediates_start = NULL;
self->strings_start = NULL;
self->read_index = 0;
- self->num_strings = 0;
self->num_intermediates = 0;
+ self->num_strings = 0;
+ self->num_functions = 0;
cleanup_if_error(amal_program_append_header(self));
return 0;
@@ -189,6 +194,14 @@ static CHECK_RESULT int amal_program_read_strings(amal_program *self) {
return AMAL_PROGRAM_OK;
}
+static CHECK_RESULT int amal_program_read_functions(amal_program *self) {
+ if(bytes_left_to_read(self) < 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_get_intermediate_by_index(amal_program *self, u16 index, Number *result) {
if(index >= self->num_intermediates)
return AMAL_PROGRAM_INSTRUCTION_INVALID_INTERMEDIATE_INDEX;
@@ -216,10 +229,12 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_
u32 instructions_size;
u32 read_start;
u32 read_end;
+ u16 func_counter;
bool inside_func;
inside_func = bool_false;
(void)inside_func;
+ func_counter = 0;
if(bytes_left_to_read(self) < sizeof(instructions_size))
return AMAL_PROGRAM_INVALID_INSTRUCTIONS_SIZE;
@@ -235,12 +250,15 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_
on the type of the register.
*/
+ return_if_error(amal_executor_instructions_start(executor, self->num_functions));
+
read_start = self->read_index;
read_end = read_start + instructions_size;
while(self->read_index < read_end) {
AmalOpcode opcode;
opcode = self->data.data[self->read_index];
self->read_index += sizeof(AmalOpcodeType);
+ /* TODO: Check instruction length and check if that amount of bytes can be read */
switch(opcode) {
case AMAL_OP_NOP: {
return_if_error(amal_exec_nop(executor));
@@ -334,12 +352,17 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_
self->read_index += 2;
break;
}
- case AMAL_OP_CALL:
- /*assert(bool_false && "TODO: Implement CALL");*/
+ case AMAL_OP_CALL: {
+ u16 func_index;
+ u8 num_args;
+ 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;
break;
+ }
case AMAL_OP_CALLR:
- /*assert(bool_false && "TODO: Implement CALLR");*/
+ assert(bool_false && "TODO: Implement CALLR");
self->read_index += 2;
break;
case AMAL_OP_CMP: {
@@ -361,13 +384,19 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_
self->read_index += 2;
break;
}
- case AMAL_OP_RET:
- return_if_error(amal_exec_ret(executor));
+ case AMAL_OP_RET: {
+ const u8 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;
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;
@@ -383,6 +412,8 @@ static CHECK_RESULT int amal_program_read_instructions(amal_program *self, amal_
}
}
+ assert(self->read_index == read_end);
+ return_if_error(amal_executor_instructions_end(executor));
return AMAL_PROGRAM_OK;
}
@@ -396,6 +427,7 @@ int amal_program_run(amal_program *self) {
while(bytes_left_to_read(self) > 0) {
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_instructions(self, executor));
}
result = amal_executor_run(executor);