wip: working on extern in VM

- Feat: add usage of vm reader instead of old way in vm.c
- Ref: update debug opcodes printing
This commit is contained in:
samsonium
2026-11-05 23:23:38 +03:00
parent 1db42c1e8e
commit d95ff88b66
19 changed files with 133 additions and 146 deletions
+2
View File
@@ -165,9 +165,11 @@ if (NOT FZL_SKIP_VM)
src/vm/reader/vm_rd_extern_libs.c
src/vm/reader/vm_rd_extern_types.c
src/vm/reader/vm_rd_header.c
src/vm/reader/vm_rd_ops.c
src/vm/reader/vm_rd_sections_sz.c
src/vm/fzl_vm.c
src/vm/fzl_vm_env.c
src/vm/fzl_vm_reader.c
src/vm/fzl_vm_debug.c
src/vm/main.c)
+3 -13
View File
@@ -1,26 +1,16 @@
#ifndef FZL_VM_H
#define FZL_VM_H
#include <common/fzl_value.h>
#include <compiler/utils/fzl_const_pool.h> // NOTE: move outside compiler scope to common
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <vm/fzl_vm_env.h>
#include <vm/fzl_vm_extern.h>
#include <vm/fzl_vm_object.h>
#include <vm/fzl_vm_reader.h>
// VM descriptor
typedef struct
{
fzl_const_t *consts;
size_t consts_count;
fzl_vm_extern_t *externs;
size_t externs_count;
uint64_t *ops;
size_t ops_count;
fzl_vm_reader_t *reader;
size_t ip;
@@ -41,7 +31,7 @@ typedef struct
} fzl_vm_t;
// Allocate FZL VM
fzl_vm_t *fzl_mkvm(const char *filepath);
fzl_vm_t *fzl_mkvm(fzl_vm_reader_t *reader);
// Load and run code
int fzl_vm_run(fzl_vm_t *vm);
+11 -91
View File
@@ -12,6 +12,7 @@
#include <vm/fzl_vm.h>
#include <vm/fzl_vm_env.h>
#include <vm/fzl_vm_object.h>
#include <vm/fzl_vm_reader.h>
#include <vm/internals/opcode.h>
char last_err[256];
@@ -20,8 +21,14 @@ size_t total_jmp_on_same = 0;
static char *expect_hdr = "FZL\0\2";
fzl_vm_t *fzl_mkvm(const char *filepath)
fzl_vm_t *fzl_mkvm(fzl_vm_reader_t *reader)
{
if (!reader)
{
snprintf(last_err, sizeof(last_err), "reader is not provided");
return NULL;
}
fzl_vm_t *vm = malloc(sizeof(fzl_vm_t));
if (!vm)
{
@@ -30,86 +37,7 @@ fzl_vm_t *fzl_mkvm(const char *filepath)
}
memset(vm, 0, sizeof(fzl_vm_t));
FILE *fd = fopen(filepath, "rb");
if (!fd)
{
snprintf(last_err, sizeof(last_err), "failed to open file '%s'", filepath);
free(vm);
return NULL;
}
char hdr[5];
fread(hdr, sizeof(char), 5,
fd); // NOTE: add red bytes check (also for freads below)
if (memcmp(hdr, expect_hdr, 5) != 0)
{
snprintf(last_err, sizeof(last_err), "magic check error");
fclose(fd);
free(vm);
return NULL;
}
size_t consts_count, ops_count;
fread(&consts_count, sizeof(size_t), 1, fd);
fread(&ops_count, sizeof(size_t), 1, fd);
// TODO: read externs count
if (ops_count < 1)
{
snprintf(last_err, sizeof(last_err), "there is nothing to do (0 ops)");
fclose(fd);
free(vm);
return NULL;
}
if (consts_count > 0)
{
vm->consts_count = consts_count;
vm->consts = malloc(consts_count * sizeof(fzl_value_t));
for (size_t i = 0; i < consts_count; i++)
{
fzl_consttype_t type;
fread(&type, sizeof(fzl_consttype_t), 1, fd);
if (type == FZL_CONSTTYPE_STRING)
{
size_t length;
char *chars;
fread(&length, sizeof(size_t), 1, fd);
chars = malloc(length * sizeof(char) + 1);
fread(chars, sizeof(char), length, fd);
chars[length] = 0;
vm->consts[i] = (fzl_const_t){
.type = type, .as.string.length = length, .as.string.chars = chars};
}
else
{
fclose(fd);
free(vm->consts);
free(vm);
snprintf(last_err, sizeof(last_err), "unknown const type at index %ld",
i);
return NULL;
}
}
}
vm->ops_count = ops_count;
vm->ops = malloc(ops_count * sizeof(uint64_t));
for (size_t i = 0; i < ops_count; i++)
{
uint64_t op;
fread(&op, sizeof(uint64_t), 1, fd);
vm->ops[i] = op;
}
// TODO: read externs
fclose(fd);
vm->reader = reader;
return vm;
}
@@ -229,9 +157,9 @@ int fzl_vm_run(fzl_vm_t *vm)
vm->ip = 0;
int result = 0;
while (vm->ip < vm->ops_count)
while (vm->ip < vm->reader->ops_count)
{
fzl_opcode_t opcode = vm->ops[vm->ip];
fzl_opcode_t opcode = vm->reader->ops[vm->ip];
size_t op_group = (opcode >> 16) & 0xFF;
size_t op_fnnum = (opcode & 0xFF);
@@ -265,13 +193,5 @@ void fzl_freevm(fzl_vm_t *vm)
while (vm->etop > 0)
fzl_freeenv(vm->estack[--vm->etop]);
for (size_t i = 0; i < vm->consts_count; i++)
{
if (vm->consts[i].type == FZL_CONSTTYPE_STRING)
free((void *)vm->consts[i].as.string.chars);
}
free(vm->consts);
free(vm->ops);
free(vm);
}
+21 -20
View File
@@ -1,4 +1,5 @@
#include <common/fzl_opcodes.h>
#include <common/fzl_value.h>
#include <stdbool.h>
#include <stdio.h>
#include <vm/fzl_vm.h>
@@ -8,36 +9,36 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
if (!vm)
return;
if (vm->ops_count < 1)
if (vm->reader->ops_count < 1)
{
printf("no opcodes\n");
return;
}
for (size_t i = 0; i < vm->ops_count; i++)
for (size_t i = 0; i < vm->reader->ops_count; i++)
{
printf("%04ld: ", i);
switch (vm->ops[i])
switch (vm->reader->ops[i])
{
case FZL_OPCODE_STORE_LOCAL:
{
size_t depth = vm->ops[++i];
size_t slot = vm->ops[++i];
size_t depth = vm->reader->ops[++i];
size_t slot = vm->reader->ops[++i];
printf("STORE_LOCAL D=%zu S=%zu\n", depth, slot);
break;
}
case FZL_OPCODE_LOAD_LOCAL:
{
size_t depth = vm->ops[++i];
size_t slot = vm->ops[++i];
size_t depth = vm->reader->ops[++i];
size_t slot = vm->reader->ops[++i];
printf("LOAD_LOCAL D=%zu S=%zu\n", depth, slot);
break;
}
case FZL_OPCODE_BUILD_STR:
printf("BUILD_STR %zu\n", vm->ops[++i]);
printf("BUILD_STR %zu\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_DEREFERENCE:
@@ -65,20 +66,20 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
break;
case FZL_OPCODE_ALLOC_OBJECT:
printf("ALLOC_OBJECT: %lu fields\n", vm->ops[++i]);
printf("ALLOC_OBJECT: %lu fields\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_GET_FIELD:
printf("GET_FIELD #%lu\n", vm->ops[++i]);
printf("GET_FIELD #%lu\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_SET_FIELD:
printf("SET_FIELD #%lu\n", vm->ops[++i]);
printf("SET_FIELD #%lu\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_CALL:
{
size_t ip = vm->ops[++i];
size_t ip = vm->reader->ops[++i];
printf("CALL IP: %lu\n", ip);
break;
}
@@ -89,22 +90,22 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
case FZL_OPCODE_LOADCONST:
{
size_t const_n = vm->ops[++i];
fzl_const_t c = vm->consts[const_n];
printf("LOADCONST #%lu ('%s')\n", const_n, c.as.string.chars);
size_t const_n = vm->reader->ops[++i];
fzl_value_t c = vm->reader->consts[const_n];
printf("LOADCONST #%lu ('%s')\n", const_n, c.as.s.value);
break;
}
case FZL_OPCODE_CALL_BUILTIN:
printf("CALL_BUILTIN #%lu\n", vm->ops[++i]);
printf("CALL_BUILTIN #%lu\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_PUSHNUM:
printf("PUSHNUM %lu\n", vm->ops[++i]);
printf("PUSHNUM %lu\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_PUSHBOOL:
printf("PUSHBOOL %s\n", vm->ops[++i] ? "true" : "false");
printf("PUSHBOOL %s\n", vm->reader->ops[++i] ? "true" : "false");
break;
case FZL_OPCODE_MK_ENVTABLE:
@@ -177,11 +178,11 @@ void fzl_vm_print_ops(fzl_vm_t *vm)
break;
case FZL_OPCODE_JZ:
printf("JZ IP: %ld\n", vm->ops[++i]);
printf("JZ IP: %ld\n", vm->reader->ops[++i]);
break;
case FZL_OPCODE_JMP:
printf("JMP IP: %ld\n", vm->ops[++i]);
printf("JMP IP: %ld\n", vm->reader->ops[++i]);
break;
}
}
+2
View File
@@ -112,6 +112,8 @@ bool fzl_vm_read(fzl_vm_reader_t *reader)
return false;
}
fclose(fd);
return true;
}
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+4 -4
View File
@@ -132,8 +132,8 @@ int op_write(fzl_vm_t *vm)
int op_load_local(fzl_vm_t *vm)
{
size_t depth = vm->ops[++vm->ip];
size_t slot = vm->ops[++vm->ip];
size_t depth = vm->reader->ops[++vm->ip];
size_t slot = vm->reader->ops[++vm->ip];
if (depth >= vm->etop)
{
@@ -168,8 +168,8 @@ int op_store_local(fzl_vm_t *vm)
fzl_value_t value = vm->dstack[--vm->dtop];
size_t depth = vm->ops[++vm->ip];
size_t slot = vm->ops[++vm->ip];
size_t depth = vm->reader->ops[++vm->ip];
size_t slot = vm->reader->ops[++vm->ip];
if (depth >= vm->etop)
{
+4 -3
View File
@@ -1,16 +1,17 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
// Jump at specified address
int op_jmp(fzl_vm_t *vm)
{
if (vm->ops_count <= vm->ip)
if (vm->reader->ops_count <= vm->ip)
{
snprintf(last_err, sizeof(last_err), "runtime error - expected JMP addr");
return -1;
}
uint64_t jmp_ip = vm->ops[++vm->ip];
uint64_t jmp_ip = vm->reader->ops[++vm->ip];
if (!vm->allow_infinite)
{
if (jmp_ip == last_jmp_ip)
@@ -46,7 +47,7 @@ int op_jz(fzl_vm_t *vm)
}
fzl_value_t jzval = vm->dstack[--vm->dtop];
uint64_t jzip = vm->ops[++vm->ip] - 1;
uint64_t jzip = vm->reader->ops[++vm->ip] - 1;
if (jzval.as.b == 0)
vm->ip = jzip;
+2 -1
View File
@@ -1,10 +1,11 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
// Call function (store return address and jump into function init)
int op_call(fzl_vm_t *vm)
{
uint64_t ip = vm->ops[++vm->ip];
uint64_t ip = vm->reader->ops[++vm->ip];
vm->cstack[vm->ctop++] = vm->ip;
vm->ip = ip - 1;
return 0;
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+4 -3
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vm/fzl_vm.h>
@@ -57,7 +58,7 @@ void escape_recursive(fzl_vm_env_t *current, fzl_vm_env_t *parent,
// Allocate specified count of fields and create object
int op_alloc_object(fzl_vm_t *vm)
{
uint64_t values_count = vm->ops[++vm->ip];
uint64_t values_count = vm->reader->ops[++vm->ip];
fzl_vm_object_t *obj = malloc(sizeof(fzl_vm_object_t));
if (values_count < 1)
@@ -94,7 +95,7 @@ int op_get_field(fzl_vm_t *vm)
return -1;
}
uint64_t field_slot = vm->ops[++vm->ip];
uint64_t field_slot = vm->reader->ops[++vm->ip];
fzl_value_t val = vm->dstack[--vm->dtop];
if (val.type != FZL_TYPE_OBJECT)
{
@@ -130,7 +131,7 @@ int op_set_field(fzl_vm_t *vm)
return -1;
}
uint64_t field_slot = vm->ops[++vm->ip];
uint64_t field_slot = vm->reader->ops[++vm->ip];
fzl_value_t objval = vm->dstack[--vm->dtop];
fzl_value_t wrval = vm->dstack[--vm->dtop];
if (objval.type != FZL_TYPE_OBJECT)
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+8 -9
View File
@@ -1,21 +1,20 @@
#include <common/fzl_builtins.h>
#include <common/fzl_value.h>
#include <stdio.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
// Load constant onto stack
int op_loadconst(fzl_vm_t *vm)
{
uint64_t cn = vm->ops[++vm->ip];
if (vm->consts_count <= cn)
uint64_t cn = vm->reader->ops[++vm->ip];
if (vm->reader->consts_count <= cn)
{
snprintf(last_err, sizeof(last_err), "runtime error - unknown const");
print_err_data(vm);
return -1;
}
fzl_const_t c = vm->consts[cn];
vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_STRING,
.as.s.length = c.as.string.length,
.as.s.value = c.as.string.chars};
vm->dstack[vm->dtop++] = vm->reader->consts[cn];
return 0;
}
@@ -23,7 +22,7 @@ int op_loadconst(fzl_vm_t *vm)
// Call builtin function
int op_call_builtin(fzl_vm_t *vm)
{
uint64_t fn_id = vm->ops[++vm->ip];
uint64_t fn_id = vm->reader->ops[++vm->ip];
if (fn_id == FZL_BUILTIN_PRINTLINE)
{
fzl_value_t arg = vm->dstack[--vm->dtop];
@@ -64,7 +63,7 @@ int op_call_builtin(fzl_vm_t *vm)
// Push number onto stack
int op_pushnum(fzl_vm_t *vm)
{
uint64_t push_n = vm->ops[++vm->ip];
uint64_t push_n = vm->reader->ops[++vm->ip];
vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_UINT, .as.u = push_n};
return 0;
}
@@ -72,7 +71,7 @@ int op_pushnum(fzl_vm_t *vm)
// Push boolean onto stack
int op_pushbool(fzl_vm_t *vm)
{
uint64_t push_b = vm->ops[++vm->ip];
uint64_t push_b = vm->reader->ops[++vm->ip];
vm->dstack[vm->dtop++] = (fzl_value_t){.type = FZL_TYPE_BOOL, .as.b = push_b};
return 0;
}
+16 -1
View File
@@ -1,3 +1,5 @@
#include <common/fzl_extern.h>
#include <common/fzl_types.h>
#include <stdio.h>
#include <string.h>
#include <vm/fzl_vm.h>
@@ -8,7 +10,7 @@ char build_result[512];
// Build string from specified count using stack values
int op_build_str(fzl_vm_t *vm)
{
uint64_t n = vm->ops[++vm->ip];
uint64_t n = vm->reader->ops[++vm->ip];
if (vm->dtop < n)
{
snprintf(last_err, sizeof(last_err),
@@ -34,6 +36,19 @@ int op_build_str(fzl_vm_t *vm)
switch (val.type)
{
case FZL_TYPE_HANDLE:
snprintf(temp, sizeof(temp), "pointer<%p>", val.as.obj);
strcpy(build_result + gi, temp);
gi += strlen(temp);
break;
case FZL_TYPE_STRUCT:
snprintf(temp, sizeof(temp), "field(values: %zu)",
((fzl_extern_type_t *)val.as.obj)->structure.fields_count);
strcpy(build_result + gi, temp);
gi += strlen(temp);
break;
case FZL_TYPE_UINT:
snprintf(temp, sizeof(temp), "%zu", val.as.u);
strcpy(build_result + gi, temp);
+1
View File
@@ -1,3 +1,4 @@
#include <stdio.h>
#include <string.h>
#include <vm/fzl_vm.h>
#include <vm/internals/opcode.h>
+20 -1
View File
@@ -6,6 +6,7 @@
#include <stdlib.h>
#include <string.h>
#include <vm/fzl_vm.h>
#include <vm/fzl_vm_reader.h>
typedef struct
{
@@ -113,10 +114,28 @@ int main(int argc, char **argv)
return 0;
}
fzl_vm_t *vm = fzl_mkvm(args->filepath);
fzl_vm_reader_t *reader = fzl_vm_mkreader(args->filepath);
if (!reader)
{
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_getreadererror());
free(args);
return -1;
}
bool result = fzl_vm_read(reader);
if (!result)
{
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_getreadererror());
fzl_vm_freereader(reader);
free(args);
return -1;
}
fzl_vm_t *vm = fzl_mkvm(reader);
if (!vm)
{
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_geterror());
fzl_vm_freereader(reader);
free(args);
return -1;
}
+30
View File
@@ -0,0 +1,30 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <vm/internals/reader.h>
// Read opcodes
bool vm_rd_ops(fzl_vm_reader_t *reader, FILE *fd)
{
if (!reader || !fd)
return false;
size_t ops_count = reader->ops_count;
if (!ops_count)
return false;
reader->ops = malloc(sizeof(size_t) * ops_count);
if (!reader->ops)
return false;
for (size_t i = 0; i < ops_count; i++)
{
size_t opcode;
if (!vm_rd_word(fd, 1, &opcode))
return false;
reader->ops[i] = opcode;
}
return true;
}