diff --git a/src/compiler.c b/src/compiler.c index 61dfec3..6798e3f 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -34,6 +34,38 @@ void demo_add_compile(Value *memory) { } +void demo_function_call_compile(Value *memory) { + uint32_t i = 0; + memory[i++].u = OP(OP_LOADU, 0, 0, 0); + memory[i++].u = 0; + memory[i++].u = OP(OP_LOADU, 1, 0, 0); + memory[i++].u = 5; + memory[i++].u = OP(OP_LOADU, 2, 0, 0); + memory[i++].u = 1; + memory[i++].u = OP(OP_LOADF, 3, 0, 0); + memory[i++].f = 5.0f; + memory[i++].u = OP(OP_LOADF, 4, 0, 0); + memory[i++].f = 5.0f; + memory[i++].u = OP(OP_LOADU, 5, 0, 0); + memory[i++].u = 200; + memory[i++].u = OP(OP_LOADU, 6, 0, 0); + memory[i++].u = 250; + memory[i++].u = OP(OP_LOADU, 7, 0, 0); + memory[i++].u = 252; + uint32_t jmp = i; + memory[i++].u = OP(OP_ADD_REAL, 4, 4, 3); + memory[i++].u = OP(OP_SUB_UINT, 1, 1, 2); + memory[i++].u = OP(OP_JGT_UINT, jmp, 1, 0); + memory[i++].u = OP(OP_REAL_TO_STRING, 5, 4, 0); + memory[i++].u = OP(OP_PRINT_STRING, 0, 5, 0); + memory[i++].u = OP(OP_REAL_TO_UINT, 1, 4, 4); + memory[i++].u = OP(OP_UINT_TO_STRING, 6, 1, 0); + memory[i++].u = OP(OP_PRINT_STRING, 0, 6, 0); + memory[i++].u = OP(OP_READ_STRING, 7, 0, 0); + memory[i++].u = OP(OP_PRINT_STRING, 0, 7, 0); + memory[i++].u = OP(OP_HALT, 0, 0, 0); +} + static void letDeclaration() { /* uint8_t global = parseVariable("Expect variable name."); */ diff --git a/src/compiler.h b/src/compiler.h index 9fc12e0..311128a 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -3,7 +3,8 @@ #include "opcodes.h" -void demo_add_compile (Value* memory); +void demo_add_compile (Value *memory); +void demo_function_call_compile(Value *memory); void compile (Value* memory, char *buffer); #endif diff --git a/src/opcodes.h b/src/opcodes.h index 50d6ef0..842761b 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -17,23 +17,25 @@ typedef struct { #define MAX_REGS 256 typedef struct { - Value registers[MAX_REGS]; /* R0-R255 */ - Slice allocated; + Value registers[MAX_REGS]; /* R0-R[MAX_REGS-1] */ + uint32_t rp; /* register pointer (last unused) */ + Slice allocated; /* start and end of global allocated block */ } Frame; -#define MEMORY_SIZE 1024 -#define STACK_SIZE 128 +#define MEMORY_SIZE 65536 +#define FRAME_STACK_SIZE 32 #define RETURN_STACK_SIZE 256 typedef struct { - Value memory[MEMORY_SIZE]; /* Memory array */ - uint32_t memory_size; - Value return_stack[RETURN_STACK_SIZE]; - uint32_t return_stack_size; - Frame stack[STACK_SIZE]; - uint32_t stack_size; - uint32_t rp; /* Return stack pointer (top of stack) */ - uint32_t sp; /* Stack pointer (top of stack) */ uint32_t pc; /* Program counter */ + uint32_t fp; /* Frame pointer (last allocated value) */ + uint32_t rp; /* Return stack pointer (top of stack) */ + uint32_t mp; /* Memory pointer (last allocated value) */ + uint32_t frame_stack_size; + Frame frame_stack[FRAME_STACK_SIZE]; + uint32_t return_stack_size; + Value return_stack[RETURN_STACK_SIZE]; + uint32_t memory_size; + Value memory[MEMORY_SIZE]; /* Memory array */ } VM; typedef enum { diff --git a/src/vm.c b/src/vm.c index f407ff5..b5b9410 100644 --- a/src/vm.c +++ b/src/vm.c @@ -3,18 +3,18 @@ #define COMPARE_AND_JUMP(type, accessor, op) \ do { \ - type value = vm->stack[vm->sp].registers[src1].accessor; \ - type value2 = vm->stack[vm->sp].registers[src2].accessor; \ + type value = vm->frame_stack[vm->fp].registers[src1].accessor; \ + type value2 = vm->frame_stack[vm->fp].registers[src2].accessor; \ vm->pc = (value op value2) ? dest : vm->pc; \ return true; \ } while (0) #define MATH_OP(accessor, op) \ do { \ - vm->stack[vm->sp].registers[dest].accessor = \ - vm->stack[vm->sp] \ + vm->frame_stack[vm->fp].registers[dest].accessor = \ + vm->frame_stack[vm->fp] \ .registers[src1] \ - .accessor op vm->stack[vm->sp] \ + .accessor op vm->frame_stack[vm->fp] \ .registers[src2] \ .accessor; \ return true; \ @@ -53,36 +53,45 @@ bool step_vm(VM *vm) { case OP_HALT: return false; case OP_CALL: - vm->return_stack[vm->rp++].u = vm->pc; /* push the return address */ - vm->sp++; /* increment to the next free frame */ - + vm->return_stack[++vm->rp].u = vm->pc; /* push return address */ + vm->pc = vm->frame_stack[vm->fp] + .registers[dest] + .u; /* set pc to location of function in memory */ + vm->fp++; /* increment to the next free frame */ + vm->frame_stack[vm->fp].allocated.start = + vm->mp; /* set start of new memory block */ return true; case OP_RETURN: - vm->pc = vm->return_stack[vm->rp].u; /* set pc to return address */ - Slice s = vm->stack[vm->rp].allocated; - memset(&vm->memory[s.start], 0, s.end - s.start); /* deallocate memory from slice */ - vm->return_stack[vm->rp--].u = 0; /* deallocate the stack */ - vm->return_stack[vm->rp] = vm->stack[vm->sp].registers[0]; /* push the return value onto the return stack (always register 0) */ - - + vm->pc = vm->return_stack[vm->rp].u; /* set pc to return address */ + Slice s = vm->frame_stack[vm->fp].allocated; /* get allocated slice */ + memset(&vm->memory[s.start], 0, + s.end - s.start); /* deallocate memory from slice */ + uint32_t parent_rp = vm->frame_stack[vm->fp - 1].rp; /* get parents rp */ + vm->frame_stack[vm->fp - 1].registers[parent_rp++] = + vm->frame_stack[vm->fp] + .registers[src1]; /* set the return value to the last register in + the parent frame */ + memset(&vm->frame_stack[vm->fp], 0, sizeof(Frame)); /* reset the frame */ + vm->fp--; /* pop the frame */ + vm->mp = s.start; /* reset memory pointer to start of old slice */ return true; case OP_LOADI: - vm->stack[vm->sp].registers[dest].i = vm->memory[vm->pc++].i; + vm->frame_stack[vm->fp].registers[dest].i = vm->memory[vm->pc++].i; return true; case OP_LOADU: - vm->stack[vm->sp].registers[dest].u = vm->memory[vm->pc++].u; + vm->frame_stack[vm->fp].registers[dest].u = vm->memory[vm->pc++].u; return true; case OP_LOADF: - vm->stack[vm->sp].registers[dest].f = vm->memory[vm->pc++].f; + vm->frame_stack[vm->fp].registers[dest].f = vm->memory[vm->pc++].f; return true; case OP_STOREI: - vm->memory[vm->pc++].i = vm->stack[vm->sp].registers[src1].i; + vm->memory[vm->pc++].i = vm->frame_stack[vm->fp].registers[src1].i; return true; case OP_STOREU: - vm->memory[vm->pc++].u = vm->stack[vm->sp].registers[src1].u; + vm->memory[vm->pc++].u = vm->frame_stack[vm->fp].registers[src1].u; return true; case OP_STOREF: - vm->memory[vm->pc++].f = vm->stack[vm->sp].registers[src1].f; + vm->memory[vm->pc++].f = vm->frame_stack[vm->fp].registers[src1].f; return true; case OP_ADD_INT: MATH_OP(i, +); @@ -109,26 +118,27 @@ bool step_vm(VM *vm) { case OP_DIV_REAL: MATH_OP(f, /); case OP_REAL_TO_INT: - vm->stack[vm->sp].registers[dest].i = - (int32_t)(vm->stack[vm->sp].registers[src1].f); + vm->frame_stack[vm->fp].registers[dest].i = + (int32_t)(vm->frame_stack[vm->fp].registers[src1].f); return true; case OP_INT_TO_REAL: - vm->stack[vm->sp].registers[dest].f = - (float)(vm->stack[vm->sp].registers[src1].i); + vm->frame_stack[vm->fp].registers[dest].f = + (float)(vm->frame_stack[vm->fp].registers[src1].i); return true; case OP_REAL_TO_UINT: - vm->stack[vm->sp].registers[dest].u = - (uint32_t)(vm->stack[vm->sp].registers[src1].f); + vm->frame_stack[vm->fp].registers[dest].u = + (uint32_t)(vm->frame_stack[vm->fp].registers[src1].f); return true; case OP_UINT_TO_REAL: - vm->stack[vm->sp].registers[dest].f = - (float)(vm->stack[vm->sp].registers[src1].u); + vm->frame_stack[vm->fp].registers[dest].f = + (float)(vm->frame_stack[vm->fp].registers[src1].u); return true; case OP_MOV: - vm->stack[vm->sp].registers[dest] = vm->stack[vm->sp].registers[src1]; + vm->frame_stack[vm->fp].registers[dest] = + vm->frame_stack[vm->fp].registers[src1]; return true; case OP_JMP: - vm->pc = vm->stack[vm->sp].registers[src1].u; /* Jump to address */ + vm->pc = vm->frame_stack[vm->fp].registers[src1].u; /* Jump to address */ return true; case OP_JEQ_UINT: { COMPARE_AND_JUMP(uint32_t, u, ==); @@ -176,31 +186,38 @@ bool step_vm(VM *vm) { COMPARE_AND_JUMP(float, u, <=); } case OP_INT_TO_STRING: { - int32_t a = (int32_t)vm->stack[vm->sp].registers[src1].i; - uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u; + int32_t a = (int32_t)vm->frame_stack[vm->fp].registers[src1].i; /* get value */ + uint32_t str_dest = (uint32_t)vm->frame_stack[vm->fp].allocated.end; /* get start of unallocated */ + vm->frame_stack[vm->fp].registers[dest].u = str_dest; /* store ptr of string to dest register */ char buffer[32]; int len = sprintf(buffer, "%d", a); - mem_strcpy(vm->memory, buffer, len, str_dest); + mem_strcpy(vm->memory, buffer, len, str_dest); /* copy buffer to dest */ + vm->frame_stack[vm->fp].allocated.end += sizeof(uint32_t) + len * sizeof(char); /* increment to end of allocated */ return true; } case OP_UINT_TO_STRING: { - uint32_t a = (uint32_t)vm->stack[vm->sp].registers[src1].u; - uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u; + uint32_t a = (uint32_t)vm->frame_stack[vm->fp].registers[src1].u; /* get value */ + uint32_t str_dest = (uint32_t)vm->frame_stack[vm->fp].allocated.end; /* get start of unallocated */ + vm->frame_stack[vm->fp].registers[dest].u = str_dest; /* store ptr of string to dest register */ char buffer[32]; int len = sprintf(buffer, "%d", a); - mem_strcpy(vm->memory, buffer, len, str_dest); + mem_strcpy(vm->memory, buffer, len, str_dest); /* copy buffer to dest */ + vm->frame_stack[vm->fp].allocated.end += sizeof(uint32_t) + len * sizeof(char); /* increment to end of allocated */ return true; } case OP_REAL_TO_STRING: { - float a = (float)vm->stack[vm->sp].registers[src1].f; - uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u; + float a = (float)vm->frame_stack[vm->fp].registers[src1].f; /* get value */ + uint32_t str_dest = (uint32_t)vm->frame_stack[vm->fp].allocated.end; /* get start of unallocated */ + vm->frame_stack[vm->fp].registers[dest].u = str_dest; /* store ptr of string to dest register */ char buffer[32]; int len = sprintf(buffer, "%f", a); - mem_strcpy(vm->memory, buffer, len, str_dest); + mem_strcpy(vm->memory, buffer, len, str_dest); /* copy buffer to dest */ + vm->frame_stack[vm->fp].allocated.end += sizeof(uint32_t) + len * sizeof(char); /* increment to end of allocated */ return true; } case OP_READ_STRING: { - uint32_t str_dest = (uint32_t)vm->stack[vm->sp].registers[dest].u; + uint32_t str_dest = (uint32_t)vm->frame_stack[vm->fp].allocated.end; /* get start of unallocated */ + vm->frame_stack[vm->fp].registers[dest].u = str_dest; /* store ptr of string to dest register */ uint32_t buffer = str_dest + 1; uint32_t length = 0; while (1) { @@ -213,10 +230,11 @@ bool step_vm(VM *vm) { length++; } vm->memory[str_dest].u = length; + vm->frame_stack[vm->fp].allocated.end += sizeof(uint32_t) + length * sizeof(char); /* increment to end of allocated */ return true; } case OP_PRINT_STRING: { - uint32_t ptr = (uint32_t)vm->stack[vm->sp].registers[src1].u; + uint32_t ptr = (uint32_t)vm->frame_stack[vm->fp].registers[src1].u; uint32_t length = vm->memory[ptr].u; uint32_t str_src = ptr + 1; uint32_t i; @@ -230,8 +248,8 @@ bool step_vm(VM *vm) { return true; } case OP_CMP_STRING: { - uint32_t addr1 = (uint32_t)vm->stack[vm->sp].registers[src1].u; - uint32_t addr2 = (uint32_t)vm->stack[vm->sp].registers[src2].u; + uint32_t addr1 = (uint32_t)vm->frame_stack[vm->fp].registers[src1].u; + uint32_t addr2 = (uint32_t)vm->frame_stack[vm->fp].registers[src2].u; uint32_t length1 = vm->memory[addr1 - 1].u; uint32_t length2 = vm->memory[addr2 - 1].u; uint32_t equal = 1;