fix loop compile

This commit is contained in:
zongor 2025-08-24 00:06:24 -07:00
parent 8aeeebc351
commit f1edd4267f
4 changed files with 88 additions and 57 deletions

View File

@ -56,7 +56,7 @@ int main(int argc, char **argv) {
vm.memory_size = MEMORY_SIZE; vm.memory_size = MEMORY_SIZE;
if (argc == 1) { if (argc == 1) {
test_loop_compile(&vm); test_add_compile(&vm);
/* repl(&vm); */ /* repl(&vm); */
} else if (argc == 2) { } else if (argc == 2) {
compileFile(argv[1], &vm); compileFile(argv[1], &vm);

View File

@ -83,6 +83,7 @@ typedef enum {
OP_LOADI, /* lodi : dest = next memory location as int */ OP_LOADI, /* lodi : dest = next memory location as int */
OP_LOADU, /* lodu : dest = next memory location as uint */ OP_LOADU, /* lodu : dest = next memory location as uint */
OP_LOADF, /* lodf : dest = next memory location as float */ OP_LOADF, /* lodf : dest = next memory location as float */
OP_LOADP, /* lodp : dest = &[next memory location] */
OP_STOREI, /* stri : next memory location = src1 as int */ OP_STOREI, /* stri : next memory location = src1 as int */
OP_STOREU, /* stru : next memory location = src1 as uint */ OP_STOREU, /* stru : next memory location = src1 as uint */
OP_STOREF, /* strf : next memory location = src1 as float */ OP_STOREF, /* strf : next memory location = src1 as float */
@ -151,6 +152,6 @@ typedef enum {
} Devicecode; } Devicecode;
/* defines a uint32 opcode */ /* defines a uint32 opcode */
#define OP(opcode, a, b, c) ((opcode << 24) | (a << 16) | (b << 8) | c) #define OP(opcode, dest, src1, src2) ((opcode << 24) | (dest << 16) | (src1 << 8) | src2)
#endif #endif

View File

@ -4,10 +4,10 @@
bool test_add_compile(VM *vm) { bool test_add_compile(VM *vm) {
vm->code[vm->cp++].u = OP(OP_LOADU, 0, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADU, 0, 0, 0);
vm->code[vm->cp++].u = 0; vm->code[vm->cp++].u = 0;
int_alloc(vm, 1); nat_alloc(vm, 1);
vm->code[vm->cp++].u = OP(OP_LOADU, 1, 1, 0); vm->code[vm->cp++].u = OP(OP_LOADU, 1, 1, 0);
vm->code[vm->cp++].u = 1; vm->code[vm->cp++].u = 1;
int_alloc(vm, 2); nat_alloc(vm, 2);
vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */ vm->code[vm->cp++].u = OP(OP_ADD_UINT, 2, 1, 0); /* let sum = 1 + 2; */
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0); vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 2, 0);
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(sum.toS()); */
@ -29,8 +29,8 @@ bool test_loop_compile(VM *vm) {
addr = int_alloc(vm, -1); addr = int_alloc(vm, -1);
vm->code[vm->cp++].u = addr; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */ vm->code[vm->cp++].u = OP(OP_LOADU, 4, 0, 0); /* loop start */
int_alloc(vm, vm->cp + 1); addr = int_alloc(vm, vm->cp + 1);
vm->code[vm->cp++].u = 4; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_LOADF, 5, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADF, 5, 0, 0);
addr = real_alloc(vm, 5.0f); addr = real_alloc(vm, 5.0f);
vm->code[vm->cp++].u = addr; vm->code[vm->cp++].u = addr;
@ -38,11 +38,10 @@ bool test_loop_compile(VM *vm) {
vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */ vm->code[vm->cp++].u = OP(OP_ADD_INT, 1, 1, 3); /* (implied by loop) i = i + (-1) */
vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */ vm->code[vm->cp++].u = OP(OP_JGE_INT, 4, 1, 2); /* } */
vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */ vm->code[vm->cp++].u = OP(OP_REAL_TO_UINT, 1, 0, 0); /* let b = a as nat; */
vm->code[vm->cp++].u = OP(OP_LOADU, 5, 0, 0); vm->code[vm->cp++].u = OP(OP_LOADP, 6, 0, 0);
addr = str_alloc(vm, "Enter a string:", 0); addr = str_alloc(vm, "Enter a string:", 0);
printf("addr=%d\n", addr);
vm->code[vm->cp++].u = addr; vm->code[vm->cp++].u = addr;
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 5, 0); /* print("Enter a string: "); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 6, 0); /* print("Enter a string: "); */
vm->code[vm->cp++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */ vm->code[vm->cp++].u = OP(OP_READ_STRING, 2, 0, 0); /* let user_string = gets(); */
vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0); vm->code[vm->cp++].u = OP(OP_UINT_TO_STRING, 3, 1, 0);
vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */ vm->code[vm->cp++].u = OP(OP_PRINT_STRING, 0, 3, 0); /* print(a.toS()); */

127
src/vm.c
View File

@ -27,8 +27,9 @@
* Embeds a string into the VM * Embeds a string into the VM
*/ */
uint32_t str_alloc(VM *vm, const char *str, uint32_t length) { uint32_t str_alloc(VM *vm, const char *str, uint32_t length) {
if (!length) if (!length) {
length = strlen(str); length = strlen(str);
}
uint32_t str_addr = vm->mp; uint32_t str_addr = vm->mp;
vm->memory[vm->mp++].u = length; vm->memory[vm->mp++].u = length;
uint32_t i, j = 0; uint32_t i, j = 0;
@ -77,8 +78,9 @@ bool step_vm(VM *vm) {
uint8_t src2 = instruction & 0xFF; uint8_t src2 = instruction & 0xFF;
switch (opcode) { switch (opcode) {
case OP_HALT: case OP_HALT: {
return false; return false;
}
case OP_CALL: { case OP_CALL: {
uint32_t jmp = vm->code[vm->pc++].u; /* location of function in code */ uint32_t jmp = vm->code[vm->pc++].u; /* location of function in code */
vm->return_stack[vm->rp++].u = vm->pc; /* set return address */ vm->return_stack[vm->rp++].u = vm->pc; /* set return address */
@ -88,61 +90,73 @@ bool step_vm(VM *vm) {
vm->pc = jmp; vm->pc = jmp;
return true; return true;
} }
case OP_RETURN: case OP_RETURN: {
vm->frames[vm->fp].rp = 0; /* reset register ptr */ vm->frames[vm->fp].rp = 0; /* reset register ptr */
vm->pc = vm->return_stack[--vm->rp].u; /* set pc to return address */ vm->pc = vm->return_stack[--vm->rp].u; /* set pc to return address */
vm->mp = vm->mp =
vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start vm->frames[vm->fp--].allocated.start; /* reset memory pointer to start
of old slice, pop the frame */ of old slice, pop the frame */
return true; return true;
case OP_LOADI:{ }
case OP_LOADI: {
uint32_t ptr = vm->code[vm->pc++].u; uint32_t ptr = vm->code[vm->pc++].u;
int32_t v = vm->memory[ptr].i; int32_t v = vm->memory[ptr].i;
/* printf("loadi | ptr=%d value=%d dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].i = v; vm->frames[vm->fp].registers[dest].i = v;
return true; return true;
} }
case OP_LOADU:{ case OP_LOADU: {
uint32_t ptr = vm->code[vm->pc++].u; uint32_t ptr = vm->code[vm->pc++].u;
uint32_t v = vm->memory[ptr].u; uint32_t v = vm->memory[ptr].u;
/* printf("loadu | ptr=%d value=%d dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].u = v; vm->frames[vm->fp].registers[dest].u = v;
return true; return true;
} }
case OP_LOADF: { case OP_LOADF: {
uint32_t ptr = vm->code[vm->pc++].u; uint32_t ptr = vm->code[vm->pc++].u;
float v = vm->memory[ptr].f; float v = vm->memory[ptr].f;
/* printf("loadf | ptr=%d value=%f dest=%d\n", ptr, v, dest); */
vm->frames[vm->fp].registers[dest].f = v; vm->frames[vm->fp].registers[dest].f = v;
return true; return true;
} }
case OP_STOREI: case OP_LOADP: {
uint32_t ptr = vm->code[vm->pc++].u;
vm->frames[vm->fp].registers[dest].u = ptr;
return true;
}
case OP_STOREI: {
vm->memory[vm->code[vm->pc++].u].i = vm->frames[vm->fp].registers[src1].i; vm->memory[vm->code[vm->pc++].u].i = vm->frames[vm->fp].registers[src1].i;
return true; return true;
case OP_STOREU: }
case OP_STOREU: {
vm->memory[vm->code[vm->pc++].u].u = vm->frames[vm->fp].registers[src1].u; vm->memory[vm->code[vm->pc++].u].u = vm->frames[vm->fp].registers[src1].u;
return true; return true;
case OP_STOREF: }
case OP_STOREF: {
vm->memory[vm->code[vm->pc++].u].f = vm->frames[vm->fp].registers[src1].f; vm->memory[vm->code[vm->pc++].u].f = vm->frames[vm->fp].registers[src1].f;
return true; return true;
case OP_PUSHI: }
case OP_PUSHI: {
vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i; vm->stack[++vm->sp].i = vm->frames[vm->fp].registers[dest].i;
return true; return true;
case OP_PUSHU: }
case OP_PUSHU: {
vm->stack[++vm->sp].u = vm->frames[vm->fp].registers[dest].u; vm->stack[++vm->sp].u = vm->frames[vm->fp].registers[dest].u;
return true; return true;
case OP_PUSHF: }
case OP_PUSHF: {
vm->stack[++vm->sp].f = vm->frames[vm->fp].registers[dest].f; vm->stack[++vm->sp].f = vm->frames[vm->fp].registers[dest].f;
return true; return true;
case OP_POPI: }
case OP_POPI: {
vm->frames[vm->fp].registers[dest].i = vm->stack[vm->sp--].i; vm->frames[vm->fp].registers[dest].i = vm->stack[vm->sp--].i;
return true; return true;
case OP_POPU: }
case OP_POPU: {
vm->frames[vm->fp].registers[dest].u = vm->stack[vm->sp--].u; vm->frames[vm->fp].registers[dest].u = vm->stack[vm->sp--].u;
return true; return true;
case OP_POPF: }
case OP_POPF: {
vm->frames[vm->fp].registers[dest].f = vm->stack[vm->sp--].f; vm->frames[vm->fp].registers[dest].f = vm->stack[vm->sp--].f;
return true; return true;
}
case OP_ADD_INT: case OP_ADD_INT:
MATH_OP(i, +); MATH_OP(i, +);
case OP_SUB_INT: case OP_SUB_INT:
@ -167,23 +181,27 @@ bool step_vm(VM *vm) {
MATH_OP(f, *); MATH_OP(f, *);
case OP_DIV_REAL: case OP_DIV_REAL:
MATH_OP(f, /); MATH_OP(f, /);
case OP_REAL_TO_INT: case OP_REAL_TO_INT: {
vm->frames[vm->fp].registers[dest].i = vm->frames[vm->fp].registers[dest].i =
(int32_t)(vm->frames[vm->fp].registers[src1].f); (int32_t)(vm->frames[vm->fp].registers[src1].f);
return true; return true;
case OP_INT_TO_REAL: }
case OP_INT_TO_REAL: {
vm->frames[vm->fp].registers[dest].f = vm->frames[vm->fp].registers[dest].f =
(float)(vm->frames[vm->fp].registers[src1].i); (float)(vm->frames[vm->fp].registers[src1].i);
return true; return true;
case OP_REAL_TO_UINT: }
case OP_REAL_TO_UINT: {
vm->frames[vm->fp].registers[dest].u = vm->frames[vm->fp].registers[dest].u =
(uint32_t)(vm->frames[vm->fp].registers[src1].f); (uint32_t)(vm->frames[vm->fp].registers[src1].f);
return true; return true;
case OP_UINT_TO_REAL: }
case OP_UINT_TO_REAL: {
vm->frames[vm->fp].registers[dest].f = vm->frames[vm->fp].registers[dest].f =
(float)(vm->frames[vm->fp].registers[src1].u); (float)(vm->frames[vm->fp].registers[src1].u);
return true; return true;
case OP_REG_SWAP: }
case OP_REG_SWAP: {
vm->frames[vm->fp].registers[dest].u ^= vm->frames[vm->fp].registers[dest].u ^=
vm->frames[vm->fp].registers[src1].u; vm->frames[vm->fp].registers[src1].u;
vm->frames[vm->fp].registers[src1].u ^= vm->frames[vm->fp].registers[src1].u ^=
@ -191,12 +209,15 @@ bool step_vm(VM *vm) {
vm->frames[vm->fp].registers[dest].u ^= vm->frames[vm->fp].registers[dest].u ^=
vm->frames[vm->fp].registers[src1].u; vm->frames[vm->fp].registers[src1].u;
return true; return true;
case OP_REG_MOV: }
vm->frames[vm->fp].registers[dest].i = vm->code[vm->pc++].i; case OP_REG_MOV: {
vm->frames[vm->fp].registers[dest].i = vm->frames[vm->fp].registers[src1].i;
return true; return true;
case OP_JMP: }
case OP_JMP: {
vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */ vm->pc = vm->frames[vm->fp].registers[dest].u; /* Jump to address */
return true; return true;
}
case OP_JEQ_UINT: { case OP_JEQ_UINT: {
COMPARE_AND_JUMP(uint32_t, u, ==); COMPARE_AND_JUMP(uint32_t, u, ==);
} }
@ -244,59 +265,67 @@ bool step_vm(VM *vm) {
} }
case OP_NOT: { case OP_NOT: {
/* TODO implement not */ /* TODO implement not */
return false;
} }
case OP_INT_TO_STRING: { case OP_INT_TO_STRING: {
int32_t a = (int32_t)vm->frames[vm->fp].registers[src1].i; /* get value */ int32_t a = (int32_t)vm->frames[vm->fp].registers[src1].i; /* get value */
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%d", a); int len = sprintf(buffer, "%d", a);
str_alloc(vm, buffer, len); /* copy buffer to dest */ uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
vm->frames[vm->fp].registers[dest].u = ptr;
return true; return true;
} }
case OP_UINT_TO_STRING: { case OP_UINT_TO_STRING: {
uint32_t a = (uint32_t)vm->frames[vm->fp].registers[src1].u; /* get value */ uint32_t a = (uint32_t)vm->frames[vm->fp].registers[src1].u; /* get value */
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%d", a); int len = sprintf(buffer, "%d", a);
str_alloc(vm, buffer, len); /* copy buffer to dest */ uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
vm->frames[vm->fp].registers[dest].u = ptr;
return true; return true;
} }
case OP_REAL_TO_STRING: { case OP_REAL_TO_STRING: {
float a = (float)vm->frames[vm->fp].registers[src1].f; /* get value */ float a = (float)vm->frames[vm->fp].registers[src1].f; /* get value */
char buffer[32]; char buffer[32];
int len = sprintf(buffer, "%f", a); int len = sprintf(buffer, "%f", a);
str_alloc(vm, buffer, len); /* copy buffer to dest */ uint32_t ptr = str_alloc(vm, buffer, len); /* copy buffer to dest */
vm->frames[vm->fp].registers[dest].u = ptr;
return true; return true;
} }
case OP_READ_STRING: { case OP_READ_STRING: {
uint32_t str_dest = (uint32_t)vm->frames[vm->fp] uint32_t str_addr = vm->mp++;
.allocated.end; /* get start of unallocated */
vm->frames[vm->fp].registers[dest].u =
str_dest; /* store ptr of string to dest register */
uint32_t buffer = str_dest + 1;
uint32_t length = 0; uint32_t length = 0;
while (1) { int ch;
int ch = getchar();
if (ch == '\n' || ch == EOF) { while ((ch = getchar()) != '\n' && ch != EOF) {
vm->memory[buffer + (length / 4)].c[length % 4] = '\0'; uint32_t idx = length % 4;
break; vm->memory[vm->mp].c[idx] = (char)ch;
}
vm->memory[buffer + (length / 4)].c[length % 4] = ch;
length++; length++;
if (idx == 3)
vm->mp++;
} }
vm->memory[str_dest].u = length;
vm->frames[vm->fp].allocated.end += uint32_t i, rem = length % 4;
((length / 4) + (length % 4) + 1); /* increment to end of allocated */ if (rem != 0) {
for (i = rem; i < 4; i++) {
vm->memory[vm->mp].c[i] = '\0';
}
vm->mp++;
}
vm->memory[str_addr].u = length;
vm->frames[vm->fp].allocated.end = vm->mp;
vm->frames[vm->fp].registers[dest].u = str_addr;
return true; return true;
} }
case OP_PRINT_STRING: { case OP_PRINT_STRING: {
uint32_t ptr = (uint32_t)vm->frames[vm->fp].registers[src1].u; uint32_t ptr = (uint32_t)vm->frames[vm->fp].registers[src1].u;
uint32_t length = vm->memory[ptr].u; uint32_t length = vm->memory[ptr].u;
printf("len=%d\n", length);
uint32_t str_src = ptr + 1; uint32_t str_src = ptr + 1;
uint32_t i; uint32_t i;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4]; uint8_t ch = vm->memory[str_src + (i / 4)].c[i % 4];
printf("char=%c\n", ch);
if (ch == '\0') if (ch == '\0')
break; break;
putchar(ch); putchar(ch);
@ -349,14 +378,16 @@ bool step_vm(VM *vm) {
length; /* increment to end of allocated */ length; /* increment to end of allocated */
return true; return true;
} }
case OP_MEM_MOV: case OP_MEM_MOV: {
vm->memory[dest] = vm->memory[src1]; vm->memory[dest] = vm->memory[src1];
return true; return true;
case OP_MEM_SWAP: }
case OP_MEM_SWAP: {
vm->memory[dest].u ^= vm->memory[src1].u; vm->memory[dest].u ^= vm->memory[src1].u;
vm->memory[src1].u ^= vm->memory[dest].u; vm->memory[src1].u ^= vm->memory[dest].u;
vm->memory[dest].u ^= vm->memory[src1].u; vm->memory[dest].u ^= vm->memory[src1].u;
return true; return true;
} }
}
return false; /* something bad happened */ return false; /* something bad happened */
} }