From 5cfba62a13b20b08fed9f0029cb86658e975bcca Mon Sep 17 00:00:00 2001 From: cassowarii Date: Sat, 27 Jun 2026 21:15:32 -0700 Subject: [PATCH] some initial supports for bytecode VM --- src/common.h | 3 ++- src/data/data.h | 6 +++++ src/vm/block.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vm/block.h | 39 +++++++++++++++++++++++++++++ src/vm/bytecode.h | 36 +++++++++++++++++++++++++++ src/vm/exec.c | 1 + src/vm/exec.h | 1 + src/vm/vm.h | 6 +++++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/data/data.h create mode 100644 src/vm/block.c create mode 100644 src/vm/block.h create mode 100644 src/vm/bytecode.h create mode 100644 src/vm/exec.c create mode 100644 src/vm/exec.h create mode 100644 src/vm/vm.h diff --git a/src/common.h b/src/common.h index 75541ee..9855724 100644 --- a/src/common.h +++ b/src/common.h @@ -3,7 +3,8 @@ #include "global.h" #include "mem/mem.h" -#include "data/value.h" +#include "data/data.h" +#include "vm/vm.h" #include // for memcpy/memset #endif diff --git a/src/data/data.h b/src/data/data.h new file mode 100644 index 0000000..f3e3031 --- /dev/null +++ b/src/data/data.h @@ -0,0 +1,6 @@ +#ifndef __SARABANDE_DATA_H__ +#define __SARABANDE_DATA_H__ + +#include "data/value.h" + +#endif diff --git a/src/vm/block.c b/src/vm/block.c new file mode 100644 index 0000000..e90c047 --- /dev/null +++ b/src/vm/block.c @@ -0,0 +1,73 @@ +#include "vm/block.h" + +#define INITIAL_PROGRAM_BLOCK_SIZE 32 + +void sbVmProgram_init(sbVmProgram *pm, usize initial_arena_size) { + *pm = (sbVmProgram) {0}; + sbArena_initialize(&pm->arena, initial_arena_size); +} + +sbVmPartialBlock sbVmBlock_create(usize initial_bytecode_size, usize initial_constant_size) { + sbVmPartialBlock pb = {0}; + sbBuffer_initialize(&pb.bytecode, initial_bytecode_size); + sbBuffer_initialize(&pb.constants, initial_constant_size); + return pb; +} + +void sbVmBlock_reset(sbVmPartialBlock *pb) { + sbBuffer_reset(&pb->bytecode); + sbBuffer_reset(&pb->constants); +} + +void sbVmBlock_deinitialize(sbVmPartialBlock *pb) { + sbBuffer_deinitialize(&pb->bytecode); + sbBuffer_deinitialize(&pb->constants); +} + +void sbVmProgram_initialize(sbVmProgram *pm) { + pm->block_count = 0; + pm->block_capacity = INITIAL_PROGRAM_BLOCK_SIZE; + pm->blocks = malloc(pm->block_capacity * sizeof(sbVmBlock)); +} + +void sbVmProgram_deinitialize(sbVmProgram *pm) { + free(pm->blocks); + *pm = (sbVmProgram) {0}; +} + +sbBlockId sbVmProgram_add_block(sbVmProgram *pm, sbVmPartialBlock *pb) { + const usize bytecode_length = pb->bytecode.size; + char *bytecode = sbArena_alloc(&pm->arena, bytecode_length); + memcpy(bytecode, pb->bytecode.data, bytecode_length); + + const usize constants_length = pb->constants.size; + char *constants = sbArena_alloc(&pm->arena, constants_length); + memcpy(constants, pb->constants.data, constants_length); + + sbVmBlock bk = { + .bytecode = bytecode, + .bytecode_length = bytecode_length, + .constants = (hV*)constants, + .constants_count = constants_length / sizeof(hV), + }; + + if (pm->block_count >= pm->block_capacity) { + usize new_capacity = pm->block_capacity * 3 / 2; + if (new_capacity <= pm->block_capacity) new_capacity = pm->block_capacity + 1; + void *new_blocks = realloc(pm->blocks, new_capacity * sizeof(sbVmBlock)); + if (new_blocks) { + pm->blocks = new_blocks; + pm->block_capacity = new_capacity; + } else { + PANIC("ran out of memory while compiling program!"); + } + } + + sbBlockId result = pm->block_count; + + pm->blocks[pm->block_count] = bk; + + pm->block_count ++; + + return result; +} diff --git a/src/vm/block.h b/src/vm/block.h new file mode 100644 index 0000000..3f3919b --- /dev/null +++ b/src/vm/block.h @@ -0,0 +1,39 @@ +#include "common.h" + +/* dynamic sized block that we can more easily add + * things to while compiling */ +typedef struct sbVmPartialBlock { + sbBuffer bytecode; + sbBuffer constants; +} sbVmPartialBlock; + +/* fixed size / frozen block of bytecode */ +typedef struct sbVmBlock { + const char *bytecode; + usize bytecode_length; + const hV *constants; + usize constants_count; +} sbVmBlock; + +typedef struct sbVmProgram { + sbArena arena; + sbVmBlock *blocks; + usize block_count; + usize block_capacity; +} sbVmProgram; + +typedef usize sbBlockId; + +void sbVmProgram_init(sbVmProgram *pm, usize initial_arena_size); + +sbVmPartialBlock sbVmBlock_create(usize initial_bytecode_size, usize initial_constant_size); + +void sbVmBlock_reset(sbVmPartialBlock *pb); + +void sbVmBlock_deinitialize(sbVmPartialBlock *pb); + +void sbVmProgram_initialize(sbVmProgram *pm); + +void sbVmProgram_deinitialize(sbVmProgram *pm); + +sbBlockId sbVmProgram_add_block(sbVmProgram *pm, sbVmPartialBlock *pb); diff --git a/src/vm/bytecode.h b/src/vm/bytecode.h new file mode 100644 index 0000000..5a206b1 --- /dev/null +++ b/src/vm/bytecode.h @@ -0,0 +1,36 @@ +#ifndef __SARABANDE_BYTECODE_H__ +#define __SARABANDE_BYTECODE_H__ + +#include "global.h" + +typedef enum sbOpcode { + BC_NOP = 0, + BC_LD_CONST, + BC_LD_IMM, + BC_LD_VAR, + BC_LD_CTX, + BC_LD_UPVAL, + BC_ST_VAR, + BC_ST_UPVAL, + BC_CALL, + BC_JMP, + BC_RET = 10, + BC_SEND, + BC_OP_ADD, + BC_OP_SUB, + BC_OP_MUL, + BC_OP_DIV, + BC_OP_NEG, + BC_OP_MOD, + BC_OP_POW, + BC_OP_DEREF, + BC_LIST_NEW = 20, + BC_HASH_NEW, + BC_LIST_ADD, + BC_HASH_ADD, + BC_LONG_NUM = 253, + BC_VLONG_NUM = 254, + BC_HALT = 255, +} sbOpcode; + +#endif diff --git a/src/vm/exec.c b/src/vm/exec.c new file mode 100644 index 0000000..b39c709 --- /dev/null +++ b/src/vm/exec.c @@ -0,0 +1 @@ +#include "vm/exec.h" diff --git a/src/vm/exec.h b/src/vm/exec.h new file mode 100644 index 0000000..67c02a2 --- /dev/null +++ b/src/vm/exec.h @@ -0,0 +1 @@ +#include "common.h" diff --git a/src/vm/vm.h b/src/vm/vm.h new file mode 100644 index 0000000..24e3b76 --- /dev/null +++ b/src/vm/vm.h @@ -0,0 +1,6 @@ +#ifndef __SARABANDE_VM_H__ +#define __SARABANDE_VM_H__ + +#include "vm/bytecode.h" + +#endif -- 1.8.3.1