diff options
Diffstat (limited to 'src/program.c')
-rw-r--r-- | src/program.c | 44 |
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); |