stage0 重命名字段 修复windows函数没有进入宏包装

This commit is contained in:
zzy
2026-08-14 20:41:09 +08:00
parent c06d7247bb
commit 2a7db9e48c
8 changed files with 355 additions and 351 deletions

View File

@@ -189,7 +189,7 @@ typedef struct {
static const char *fn_name_at(spl_prog_t *prog, usize ip) { static const char *fn_name_at(spl_prog_t *prog, usize ip) {
for (usize i = 0; i < vec_size(prog->funcs); i++) { for (usize i = 0; i < vec_size(prog->funcs); i++) {
spl_func_t *f = &vec_at(prog->funcs, i); spl_vm_func_t *f = &vec_at(prog->funcs, i);
if (ip >= f->address && ip < f->address + f->ninsns) if (ip >= f->address && ip < f->address + f->ninsns)
return f->name ? f->name : "?"; return f->name ? f->name : "?";
} }
@@ -201,7 +201,7 @@ static void cur_func_bounds(spl_prog_t *prog, usize ip, usize *start, usize *end
*start = 0; *start = 0;
*end = vec_size(prog->insns); *end = vec_size(prog->insns);
for (usize i = 0; i < vec_size(prog->funcs); i++) { for (usize i = 0; i < vec_size(prog->funcs); i++) {
spl_func_t *f = &vec_at(prog->funcs, i); spl_vm_func_t *f = &vec_at(prog->funcs, i);
if (ip >= f->address && ip < f->address + f->ninsns) { if (ip >= f->address && ip < f->address + f->ninsns) {
*start = f->address; *start = f->address;
*end = f->address + f->ninsns; *end = f->address + f->ninsns;
@@ -211,9 +211,9 @@ static void cur_func_bounds(spl_prog_t *prog, usize ip, usize *start, usize *end
} }
/* 格式化一条指令(不含行号前缀) */ /* 格式化一条指令(不含行号前缀) */
static void fmt_insn(const spl_ins_t *ins, char *buf, size_t n) { static void fmt_insn(const spl_vm_ins_t *ins, char *buf, size_t n) {
snprintf(buf, n, "%-11s %-5s %zu", spl_opcode_name(ins->opcode), spl_type_tag_name(ins->type), snprintf(buf, n, "%-11s %-5s %zu", spl_vm_opcode_name(ins->opcode),
ins->imm); spl_vm_type_kind_name(ins->type), ins->imm);
} }
static void dbg_show_location(dbg_t *d) { static void dbg_show_location(dbg_t *d) {
@@ -539,7 +539,7 @@ static int cmd_x(dbg_t *d, const char *args) {
return 0; return 0;
} }
unsigned char *sbase = (unsigned char *)d->vm->stacks.data; unsigned char *sbase = (unsigned char *)d->vm->stacks.data;
usize slen = d->vm->config.max_stack_depth * sizeof(spl_val_t); usize slen = d->vm->config.max_stack_depth * sizeof(spl_vm_val_t);
printf(" addr=%#llx stack=[%p,+%zu) in=%d\n", addr, sbase, slen, printf(" addr=%#llx stack=[%p,+%zu) in=%d\n", addr, sbase, slen,
addr >= (uintptr_t)sbase && addr < (uintptr_t)(sbase + slen)); addr >= (uintptr_t)sbase && addr < (uintptr_t)(sbase + slen));
unsigned char *p = (unsigned char *)(uintptr_t)addr; unsigned char *p = (unsigned char *)(uintptr_t)addr;
@@ -567,7 +567,7 @@ static int cmd_p(dbg_t *d, const char *args) {
printf(" no variable '%s' in %s\n", args, fn); printf(" no variable '%s' in %s\n", args, fn);
return 0; return 0;
} }
spl_val_t *addr = (spl_val_t *)((char *)&d->vm->stacks.data[d->vm->fp] + v->offset); spl_vm_val_t *addr = (spl_vm_val_t *)((char *)&d->vm->stacks.data[d->vm->fp] + v->offset);
printf(" %s = %zu (0x%zx) @ fp+%zu\n", v->name, *addr, *addr, v->offset); printf(" %s = %zu (0x%zx) @ fp+%zu\n", v->name, *addr, *addr, v->offset);
d->last_ptr = (usize)*addr; /* 供 x 无参重读 */ d->last_ptr = (usize)*addr; /* 供 x 无参重读 */
return 0; return 0;

View File

@@ -25,7 +25,7 @@ int main(int argc, const char **argv) {
if (vec_size(prog.funcs) > 0) { if (vec_size(prog.funcs) > 0) {
printf(";; --- functions ---\n"); printf(";; --- functions ---\n");
for (usize i = 0; i < vec_size(prog.funcs); i++) { for (usize i = 0; i < vec_size(prog.funcs); i++) {
spl_func_t *f = &vec_at(prog.funcs, i); spl_vm_func_t *f = &vec_at(prog.funcs, i);
printf(" %s nargs=%zu ninsns=%zu addr=%zu\n", f->name ? f->name : "(anon)", f->nargs, printf(" %s nargs=%zu ninsns=%zu addr=%zu\n", f->name ? f->name : "(anon)", f->nargs,
f->ninsns, f->address); f->ninsns, f->address);
} }
@@ -35,7 +35,7 @@ int main(int argc, const char **argv) {
if (vec_size(prog.natives) > 0) { if (vec_size(prog.natives) > 0) {
printf(";; --- natives ---\n"); printf(";; --- natives ---\n");
for (int i = 0; i < (int)vec_size(prog.natives); i++) { for (int i = 0; i < (int)vec_size(prog.natives); i++) {
spl_native_t *n = &vec_at(prog.natives, i); spl_vm_native_t *n = &vec_at(prog.natives, i);
printf(" %s\n", n->name ? n->name : "(anon)"); printf(" %s\n", n->name ? n->name : "(anon)");
} }
printf("\n"); printf("\n");
@@ -51,10 +51,10 @@ int main(int argc, const char **argv) {
printf(";; --- instructions ---\n"); printf(";; --- instructions ---\n");
for (usize i = 0; i < vec_size(prog.insns); i++) { for (usize i = 0; i < vec_size(prog.insns); i++) {
spl_ins_t *ins = &vec_at(prog.insns, i); spl_vm_ins_t *ins = &vec_at(prog.insns, i);
printf("%4zd: %s", i, spl_opcode_name((spl_opcode_t)ins->opcode)); printf("%4zd: %s", i, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode));
if (ins->type != SPL_VOID) if (ins->type != SPL_VOID)
printf(" %s", spl_type_tag_name((spl_type_t)ins->type)); printf(" %s", spl_vm_type_kind_name((spl_type_t)ins->type));
printf(" %zd", ins->imm); printf(" %zd", ins->imm);
/* annotate jumps / calls */ /* annotate jumps / calls */

View File

@@ -45,16 +45,16 @@ void spl_prog_drop(spl_prog_t *prog) {
/* ---- LE read/write helpers ---- */ /* ---- LE read/write helpers ---- */
static inline spl_val_t rd64(const unsigned char **p) { static inline spl_vm_val_t rd64(const unsigned char **p) {
spl_val_t v = (spl_val_t)(*p)[0] | ((spl_val_t)(*p)[1] << 8) | ((spl_val_t)(*p)[2] << 16) | spl_vm_val_t v = (spl_vm_val_t)(*p)[0] | ((spl_vm_val_t)(*p)[1] << 8) |
((spl_val_t)(*p)[3] << 24) | ((spl_val_t)(*p)[4] << 32) | ((spl_vm_val_t)(*p)[2] << 16) | ((spl_vm_val_t)(*p)[3] << 24) |
((spl_val_t)(*p)[5] << 40) | ((spl_val_t)(*p)[6] << 48) | ((spl_vm_val_t)(*p)[4] << 32) | ((spl_vm_val_t)(*p)[5] << 40) |
((spl_val_t)(*p)[7] << 56); ((spl_vm_val_t)(*p)[6] << 48) | ((spl_vm_val_t)(*p)[7] << 56);
*p += 8; *p += 8;
return v; return v;
} }
static inline void wr64(unsigned char **p, spl_val_t v) { static inline void wr64(unsigned char **p, spl_vm_val_t v) {
*(*p)++ = (unsigned char)(v); *(*p)++ = (unsigned char)(v);
*(*p)++ = (unsigned char)(v >> 8); *(*p)++ = (unsigned char)(v >> 8);
*(*p)++ = (unsigned char)(v >> 16); *(*p)++ = (unsigned char)(v >> 16);
@@ -73,7 +73,7 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
unsigned char *data; unsigned char *data;
long len; long len;
const unsigned char *p; const unsigned char *p;
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata; spl_vm_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
if (!fname || !prog) if (!fname || !prog)
return -1; return -1;
@@ -120,9 +120,9 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
ndata = rd64(&p); ndata = rd64(&p);
/* ---- function table ---- */ /* ---- function table ---- */
for (spl_val_t i = 0; i < nfuncs; i++) { for (spl_vm_val_t i = 0; i < nfuncs; i++) {
spl_func_t func = {0}; spl_vm_func_t func = {0};
spl_val_t nlen = rd64(&p); spl_vm_val_t nlen = rd64(&p);
usize pad = ALIGN8((usize)nlen) - (usize)nlen; usize pad = ALIGN8((usize)nlen) - (usize)nlen;
func.name = (char *)malloc((usize)nlen); func.name = (char *)malloc((usize)nlen);
@@ -141,12 +141,12 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
} }
/* ---- instructions ---- */ /* ---- instructions ---- */
for (spl_val_t i = 0; i < ninsns; i++) { for (spl_vm_val_t i = 0; i < ninsns; i++) {
if ((size_t)(p - data) + 12 > (size_t)len) { if ((size_t)(p - data) + 12 > (size_t)len) {
free(data); free(data);
return -1; return -1;
} }
spl_ins_t ins; spl_vm_ins_t ins;
ins.opcode = (uint16_t)p[0] | ((uint16_t)p[1] << 8); ins.opcode = (uint16_t)p[0] | ((uint16_t)p[1] << 8);
ins.type = (uint16_t)p[2] | ((uint16_t)p[3] << 8); ins.type = (uint16_t)p[2] | ((uint16_t)p[3] << 8);
p += 4; p += 4;
@@ -155,9 +155,9 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
} }
/* ---- native table ---- */ /* ---- native table ---- */
for (spl_val_t i = 0; i < nnatives; i++) { for (spl_vm_val_t i = 0; i < nnatives; i++) {
spl_native_t nat = {0}; spl_vm_native_t nat = {0};
spl_val_t nlen = rd64(&p); spl_vm_val_t nlen = rd64(&p);
usize pad = ALIGN8((usize)nlen) - (usize)nlen; usize pad = ALIGN8((usize)nlen) - (usize)nlen;
nat.name = (char *)malloc((usize)nlen); nat.name = (char *)malloc((usize)nlen);
@@ -174,8 +174,8 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
} }
/* ---- string table ---- */ /* ---- string table ---- */
for (spl_val_t i = 0; i < nstrs; i++) { for (spl_vm_val_t i = 0; i < nstrs; i++) {
spl_val_t slen = rd64(&p); spl_vm_val_t slen = rd64(&p);
usize pad = ALIGN8((usize)slen) - (usize)slen; usize pad = ALIGN8((usize)slen) - (usize)slen;
char *s = (char *)malloc((usize)slen + 1); char *s = (char *)malloc((usize)slen + 1);
if (!s) { if (!s) {
@@ -189,8 +189,8 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
} }
/* ---- global data ---- */ /* ---- global data ---- */
for (spl_val_t i = 0; i < ndata; i++) { for (spl_vm_val_t i = 0; i < ndata; i++) {
spl_gdata_t entry; spl_vm_gdata_t entry;
entry.size = rd64(&p); entry.size = rd64(&p);
usize pad = ALIGN8(entry.size) - entry.size; usize pad = ALIGN8(entry.size) - entry.size;
entry.data = (unsigned char *)malloc(entry.size); entry.data = (unsigned char *)malloc(entry.size);
@@ -226,9 +226,9 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) { int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
unsigned char *buf, *p; unsigned char *buf, *p;
spl_val_t i; spl_vm_val_t i;
size_t total; size_t total;
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata; spl_vm_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
usize nlen, pad; usize nlen, pad;
if (!fname || !prog) if (!fname || !prog)
@@ -306,7 +306,7 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
/* ---- instructions ---- */ /* ---- instructions ---- */
for (i = 0; i < ninsns; i++) { for (i = 0; i < ninsns; i++) {
spl_ins_t *ins = &vec_at(prog->insns, i); spl_vm_ins_t *ins = &vec_at(prog->insns, i);
*p++ = (unsigned char)(ins->opcode); *p++ = (unsigned char)(ins->opcode);
*p++ = (unsigned char)(ins->opcode >> 8); *p++ = (unsigned char)(ins->opcode >> 8);
*p++ = (unsigned char)(ins->type); *p++ = (unsigned char)(ins->type);
@@ -341,7 +341,7 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
/* ---- global data ---- */ /* ---- global data ---- */
for (i = 0; i < ndata; i++) { for (i = 0; i < ndata; i++) {
spl_gdata_t *entry = &vec_at(prog->gdata, i); spl_vm_gdata_t *entry = &vec_at(prog->gdata, i);
pad = ALIGN8(entry->size) - entry->size; pad = ALIGN8(entry->size) - entry->size;
wr64(&p, entry->size); wr64(&p, entry->size);
memcpy(p, entry->data, entry->size); memcpy(p, entry->data, entry->size);
@@ -362,22 +362,22 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
return 0; return 0;
} }
int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm) { int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_vm_val_t imm) {
if (!prog) if (!prog)
return 0; return 0;
spl_ins_t ins = (spl_ins_t){.opcode = opcode, .type = type, .imm = imm}; spl_vm_ins_t ins = (spl_vm_ins_t){.opcode = opcode, .type = type, .imm = imm};
vec_push(prog->insns, ins); vec_push(prog->insns, ins);
return vec_size(prog->insns); return vec_size(prog->insns);
} }
int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func) { int spl_prog_add_func(spl_prog_t *prog, spl_vm_func_t *func) {
if (!prog || !func) if (!prog || !func)
return 0; return 0;
vec_push(prog->funcs, *func); vec_push(prog->funcs, *func);
return vec_size(prog->funcs); return vec_size(prog->funcs);
} }
int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native) { int spl_prog_add_native(spl_prog_t *prog, spl_vm_native_t *native) {
if (!prog || !native) if (!prog || !native)
return 0; return 0;
vec_push(prog->natives, *native); vec_push(prog->natives, *native);
@@ -385,7 +385,7 @@ int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native) {
} }
int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size) { int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size) {
spl_gdata_t entry; spl_vm_gdata_t entry;
if (!prog) if (!prog)
return 0; return 0;
entry.data = (unsigned char *)malloc(size); entry.data = (unsigned char *)malloc(size);
@@ -397,7 +397,7 @@ int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size) {
return vec_size(prog->gdata); return vec_size(prog->gdata);
} }
spl_func_t *spl_prog_get_func(spl_prog_t *prog, const char *name) { spl_vm_func_t *spl_prog_get_func(spl_prog_t *prog, const char *name) {
if (!prog || !name) if (!prog || !name)
return NULL; return NULL;
vec_for(prog->funcs, i) { vec_for(prog->funcs, i) {
@@ -409,7 +409,7 @@ spl_func_t *spl_prog_get_func(spl_prog_t *prog, const char *name) {
return NULL; return NULL;
} }
spl_native_t *spl_prog_get_native(spl_prog_t *prog, const char *name) { spl_vm_native_t *spl_prog_get_native(spl_prog_t *prog, const char *name) {
if (!prog || !name) if (!prog || !name)
return NULL; return NULL;
vec_for(prog->natives, i) { vec_for(prog->natives, i) {
@@ -426,8 +426,8 @@ const char *opcode_name[] = {
SPL_OPCODES(X) SPL_OPCODES(X)
#undef X #undef X
}; };
const char *spl_opcode_name(spl_opcode_t opcode) { return opcode_name[opcode]; } const char *spl_vm_opcode_name(spl_vm_opcode_t opcode) { return opcode_name[opcode]; }
const char *spl_type_tag_name(spl_type_t type) { const char *spl_vm_type_kind_name(spl_type_t type) {
switch (type) { switch (type) {
case SPL_VOID: case SPL_VOID:
return "void"; return "void";
@@ -464,10 +464,10 @@ const char *spl_type_tag_name(spl_type_t type) {
} }
} }
void spl_ins_dump(spl_ins_t *ins, spl_val_t addr) { void spl_vm_ins_dump(spl_vm_ins_t *ins, spl_vm_val_t addr) {
printf("%4zu: %s", addr, spl_opcode_name((spl_opcode_t)ins->opcode)); printf("%4zu: %s", addr, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode));
if (ins->type != SPL_VOID) if (ins->type != SPL_VOID)
printf(" %s", spl_type_tag_name((spl_type_t)ins->type)); printf(" %s", spl_vm_type_kind_name((spl_type_t)ins->type));
printf(" %zd:%zx", ins->imm, ins->imm); printf(" %zd:%zx", ins->imm, ins->imm);
printf("\n"); printf("\n");
} }

View File

@@ -103,7 +103,7 @@ typedef enum {
#define X(opcode, name, argc, pop, push, desc) opcode, #define X(opcode, name, argc, pop, push, desc) opcode,
SPL_OPCODES(X) SPL_OPCODES(X)
#undef X #undef X
} spl_opcode_t; } spl_vm_opcode_t;
/* /*
* Binary format (all metadata fields spl_val_t LE): * Binary format (all metadata fields spl_val_t LE):
@@ -151,48 +151,48 @@ typedef enum {
#define SPL_BINFMT_MAGIC "SPLBIN\0\0" #define SPL_BINFMT_MAGIC "SPLBIN\0\0"
// All SIR stack values are ptr-bit unsigned integers // All SIR stack values are ptr-bit unsigned integers
typedef usize spl_val_t; typedef usize spl_vm_val_t;
typedef struct spl_ins { typedef struct spl_vm_ins {
uint8_t opcode; uint8_t opcode;
uint8_t type; uint8_t type;
spl_val_t imm; spl_vm_val_t imm;
} spl_ins_t; } spl_vm_ins_t;
typedef VEC(spl_ins_t) spl_ins_vec_t; typedef VEC(spl_vm_ins_t) spl_vm_ins_vec_t;
typedef struct spl_func { typedef struct spl_vm_func {
char *name; char *name;
spl_val_t idx_of_strtab; spl_vm_val_t idx_of_strtab;
spl_val_t nargs; spl_vm_val_t nargs;
spl_val_t ninsns; spl_vm_val_t ninsns;
spl_val_t address; spl_vm_val_t address;
} spl_func_t; } spl_vm_func_t;
typedef VEC(spl_func_t) spl_func_vec_t; typedef VEC(spl_vm_func_t) spl_vm_func_vec_t;
/* Native function pointer type */ /* Native function pointer type */
typedef spl_val_t (*spl_fn_t)(int nargs, spl_val_t *args); typedef spl_vm_val_t (*spl_vm_fn_t)(int nargs, spl_vm_val_t *args);
typedef struct spl_native { typedef struct spl_vm_native {
char *name; char *name;
spl_val_t idx_of_strtab; spl_vm_val_t idx_of_strtab;
spl_fn_t impl_fn; spl_vm_fn_t impl_fn;
} spl_native_t; } spl_vm_native_t;
typedef VEC(spl_native_t) spl_native_vec_t; typedef VEC(spl_vm_native_t) spl_vm_native_vec_t;
typedef struct { typedef struct {
unsigned char *data; unsigned char *data;
usize size; usize size;
} spl_gdata_t; } spl_vm_gdata_t;
typedef VEC(spl_gdata_t) spl_data_t; typedef VEC(spl_vm_gdata_t) spl_vm_data_t;
typedef VEC(const char *) spl_strtab_t; typedef VEC(const char *) spl_vm_strtab_t;
typedef MAP(const char *, const char *) spl_symtab_t; typedef MAP(const char *, const char *) spl_vm_symtab_t;
/* Opaque handle for loaded program */ /* Opaque handle for loaded program */
typedef struct spl_prog { typedef struct spl_prog {
spl_ins_vec_t insns; spl_vm_ins_vec_t insns;
spl_func_vec_t funcs; spl_vm_func_vec_t funcs;
spl_native_vec_t natives; spl_vm_native_vec_t natives;
spl_data_t gdata; spl_vm_data_t gdata;
spl_strtab_t strtab; spl_vm_strtab_t strtab;
spl_symtab_t symtab; spl_vm_symtab_t symtab;
char *debug; /* 文件尾部 debug 段splc0 -g 追加的文本),无则 NULL */ char *debug; /* 文件尾部 debug 段splc0 -g 追加的文本),无则 NULL */
usize debug_size; usize debug_size;
} spl_prog_t; } spl_prog_t;
@@ -203,18 +203,18 @@ void spl_prog_drop(spl_prog_t *prog);
int spl_prog_load_from_file(const char *fname, spl_prog_t *prog); int spl_prog_load_from_file(const char *fname, spl_prog_t *prog);
int spl_prog_store_to_file(const char *fname, spl_prog_t *prog); int spl_prog_store_to_file(const char *fname, spl_prog_t *prog);
int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_val_t imm); int spl_prog_add_instr(spl_prog_t *prog, uint8_t opcode, uint8_t type, spl_vm_val_t imm);
int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size); int spl_prog_add_data(spl_prog_t *prog, void *ptr, usize size);
int spl_prog_add_func(spl_prog_t *prog, spl_func_t *func); int spl_prog_add_func(spl_prog_t *prog, spl_vm_func_t *func);
int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native); int spl_prog_add_native(spl_prog_t *prog, spl_vm_native_t *native);
spl_func_t *spl_prog_get_func(spl_prog_t *prog, const char *name); spl_vm_func_t *spl_prog_get_func(spl_prog_t *prog, const char *name);
spl_native_t *spl_prog_get_native(spl_prog_t *prog, const char *name); spl_vm_native_t *spl_prog_get_native(spl_prog_t *prog, const char *name);
/* Opcode name lookup for debugging/dumping */ /* Opcode name lookup for debugging/dumping */
const char *spl_opcode_name(spl_opcode_t opcode); const char *spl_vm_opcode_name(spl_vm_opcode_t opcode);
const char *spl_type_tag_name(spl_type_t type); const char *spl_vm_type_kind_name(spl_type_t type);
void spl_ins_dump(spl_ins_t *ins, spl_val_t addr); void spl_vm_ins_dump(spl_vm_ins_t *ins, spl_vm_val_t addr);
#endif /* __SPL_MCODE_H__ */ #endif /* __SPL_MCODE_H__ */

View File

@@ -36,44 +36,44 @@
} while (0) } while (0)
#define SYSCALL_0(name, ret_expr) \ #define SYSCALL_0(name, ret_expr) \
static spl_val_t name(int nargs, spl_val_t *args) { \ static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 0); \ CHECK_NARGS(#name, 0); \
(void)args; \ (void)args; \
return (spl_val_t)(uintptr_t)(ret_expr); \ return (spl_vm_val_t)(uintptr_t)(ret_expr); \
} }
#define SYSCALL_1(name, t1, ret_expr) \ #define SYSCALL_1(name, t1, ret_expr) \
static spl_val_t name(int nargs, spl_val_t *args) { \ static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 1); \ CHECK_NARGS(#name, 1); \
t1 a1 = (t1)(uintptr_t)args[0]; \ t1 a1 = (t1)(uintptr_t)args[0]; \
return (spl_val_t)(uintptr_t)(ret_expr); \ return (spl_vm_val_t)(uintptr_t)(ret_expr); \
} }
#define SYSCALL_2(name, t1, t2, ret_expr) \ #define SYSCALL_2(name, t1, t2, ret_expr) \
static spl_val_t name(int nargs, spl_val_t *args) { \ static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 2); \ CHECK_NARGS(#name, 2); \
t1 a1 = (t1)(uintptr_t)args[0]; \ t1 a1 = (t1)(uintptr_t)args[0]; \
t2 a2 = (t2)(uintptr_t)args[1]; \ t2 a2 = (t2)(uintptr_t)args[1]; \
return (spl_val_t)(uintptr_t)(ret_expr); \ return (spl_vm_val_t)(uintptr_t)(ret_expr); \
} }
#define SYSCALL_3(name, t1, t2, t3, ret_expr) \ #define SYSCALL_3(name, t1, t2, t3, ret_expr) \
static spl_val_t name(int nargs, spl_val_t *args) { \ static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 3); \ CHECK_NARGS(#name, 3); \
t1 a1 = (t1)(uintptr_t)args[0]; \ t1 a1 = (t1)(uintptr_t)args[0]; \
t2 a2 = (t2)(uintptr_t)args[1]; \ t2 a2 = (t2)(uintptr_t)args[1]; \
t3 a3 = (t3)(uintptr_t)args[2]; \ t3 a3 = (t3)(uintptr_t)args[2]; \
return (spl_val_t)(uintptr_t)(ret_expr); \ return (spl_vm_val_t)(uintptr_t)(ret_expr); \
} }
#define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \ #define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \
static spl_val_t name(int nargs, spl_val_t *args) { \ static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 4); \ CHECK_NARGS(#name, 4); \
t1 a1 = (t1)(uintptr_t)args[0]; \ t1 a1 = (t1)(uintptr_t)args[0]; \
t2 a2 = (t2)(uintptr_t)args[1]; \ t2 a2 = (t2)(uintptr_t)args[1]; \
t3 a3 = (t3)(uintptr_t)args[2]; \ t3 a3 = (t3)(uintptr_t)args[2]; \
t4 a4 = (t4)(uintptr_t)args[3]; \ t4 a4 = (t4)(uintptr_t)args[3]; \
return (spl_val_t)(uintptr_t)(ret_expr); \ return (spl_vm_val_t)(uintptr_t)(ret_expr); \
} }
/* ================================================================= /* =================================================================
@@ -81,7 +81,7 @@
* ================================================================= */ * ================================================================= */
/* vm_exit - terminate process with the given exit code */ /* vm_exit - terminate process with the given exit code */
SYSCALL_1(vm_exit, int, (exit(a1), (spl_val_t)0)) SYSCALL_1(vm_exit, int, (exit(a1), (spl_vm_val_t)0))
/* vm_putchar - write a single character to stdout */ /* vm_putchar - write a single character to stdout */
SYSCALL_1(vm_putchar, int, putchar(a1)) SYSCALL_1(vm_putchar, int, putchar(a1))
@@ -90,10 +90,10 @@ SYSCALL_1(vm_putchar, int, putchar(a1))
SYSCALL_0(vm_getchar, getchar()) SYSCALL_0(vm_getchar, getchar())
/* vm_putint - print an integer to stdout */ /* vm_putint - print an integer to stdout */
SYSCALL_1(vm_putint, int, (fprintf(stdout, "%d", a1), (spl_val_t)0)) SYSCALL_1(vm_putint, int, (fprintf(stdout, "%d", a1), (spl_vm_val_t)0))
/* vm_putstr - print a string to stdout (no trailing newline) */ /* vm_putstr - print a string to stdout (no trailing newline) */
SYSCALL_1(vm_putstr, const char *, (fputs(a1, stdout), (spl_val_t)0)) SYSCALL_1(vm_putstr, const char *, (fputs(a1, stdout), (spl_vm_val_t)0))
/* vm_fopen - open a file, returns FILE* as spl_val_t */ /* vm_fopen - open a file, returns FILE* as spl_val_t */
SYSCALL_2(vm_fopen, const char *, const char *, (uintptr_t)fopen(a1, a2)) SYSCALL_2(vm_fopen, const char *, const char *, (uintptr_t)fopen(a1, a2))
@@ -108,14 +108,14 @@ SYSCALL_4(vm_fread, void *, size_t, size_t, FILE *, fread(a1, a2, a3, a4))
SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4)) SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4))
/* vm_fsize - get file size in bytes */ /* vm_fsize - get file size in bytes */
static spl_val_t vm_fsize(int nargs, spl_val_t *args) { static spl_vm_val_t vm_fsize(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_fsize", 1); CHECK_NARGS("vm_fsize", 1);
FILE *f = (FILE *)(uintptr_t)args[0]; FILE *f = (FILE *)(uintptr_t)args[0];
long cur = ftell(f); long cur = ftell(f);
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
long sz = ftell(f); long sz = ftell(f);
fseek(f, cur, SEEK_SET); fseek(f, cur, SEEK_SET);
return (spl_val_t)(uintptr_t)sz; return (spl_vm_val_t)(uintptr_t)sz;
} }
SYSCALL_0(vm_stdin, stdin) SYSCALL_0(vm_stdin, stdin)
@@ -123,7 +123,7 @@ SYSCALL_0(vm_stdout, stdout)
SYSCALL_0(vm_stderr, stderr) SYSCALL_0(vm_stderr, stderr)
/* vm_read_file - read entire file into a malloc'd, null-terminated buffer */ /* vm_read_file - read entire file into a malloc'd, null-terminated buffer */
static spl_val_t vm_read_file(int nargs, spl_val_t *args) { static spl_vm_val_t vm_read_file(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_read_file", 1); CHECK_NARGS("vm_read_file", 1);
const char *path = (const char *)(uintptr_t)args[0]; const char *path = (const char *)(uintptr_t)args[0];
if (path == nullptr) { if (path == nullptr) {
@@ -146,14 +146,14 @@ static spl_val_t vm_read_file(int nargs, spl_val_t *args) {
size_t nread = fread(buf, 1, (size_t)sz, f); size_t nread = fread(buf, 1, (size_t)sz, f);
fclose(f); fclose(f);
buf[nread] = '\0'; buf[nread] = '\0';
return (spl_val_t)(uintptr_t)buf; return (spl_vm_val_t)(uintptr_t)buf;
} }
/* vm_alloc - allocate memory (malloc) */ /* vm_alloc - allocate memory (malloc) */
SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1)) SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1))
/* vm_free - free memory */ /* vm_free - free memory */
SYSCALL_1(vm_free, void *, (free(a1), (spl_val_t)0)) SYSCALL_1(vm_free, void *, (free(a1), (spl_vm_val_t)0))
/* vm_realloc - reallocate memory (realloc) */ /* vm_realloc - reallocate memory (realloc) */
SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2)) SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2))
@@ -167,7 +167,7 @@ SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2))
/* vm_memcpy - copy memory, returns dst */ /* vm_memcpy - copy memory, returns dst */
SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1)) SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1))
static spl_val_t vm_printf(int nargs, spl_val_t *args) { static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
(void)args; (void)args;
if (nargs <= 0) { if (nargs <= 0) {
return 0; return 0;
@@ -235,18 +235,18 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) {
* ================================================================= */ * ================================================================= */
/* vm_new - create a new sub-VM instance, returns spl_vm_t* */ /* vm_new - create a new sub-VM instance, returns spl_vm_t* */
static spl_val_t vm_new(int nargs, spl_val_t *args) { static spl_vm_val_t vm_new(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_new", 0); CHECK_NARGS("vm_new", 0);
(void)args; (void)args;
spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t)); spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t));
if (!vm) if (!vm)
return 0; return 0;
spl_vm_init(vm); spl_vm_init(vm);
return (spl_val_t)(uintptr_t)vm; return (spl_vm_val_t)(uintptr_t)vm;
} }
/* vm_drop - destroy a sub-VM and its loaded program */ /* vm_drop - destroy a sub-VM and its loaded program */
static spl_val_t vm_drop(int nargs, spl_val_t *args) { static spl_vm_val_t vm_drop(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_drop", 1); CHECK_NARGS("vm_drop", 1);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
if (!vm) if (!vm)
@@ -262,7 +262,7 @@ static spl_val_t vm_drop(int nargs, spl_val_t *args) {
} }
/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */ /* vm_load - load a .sir file, register syscalls, return spl_prog_t* */
static spl_val_t vm_load(int nargs, spl_val_t *args) { static spl_vm_val_t vm_load(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_load", 2); CHECK_NARGS("vm_load", 2);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
const char *path = (const char *)(uintptr_t)args[1]; const char *path = (const char *)(uintptr_t)args[1];
@@ -282,14 +282,14 @@ static spl_val_t vm_load(int nargs, spl_val_t *args) {
free(prog); free(prog);
return -1; return -1;
} }
return (spl_val_t)(uintptr_t)prog; return (spl_vm_val_t)(uintptr_t)prog;
} }
/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */ /* vm_push - push a value onto the sub-VM's stack (for passing arguments) */
static spl_val_t vm_push(int nargs, spl_val_t *args) { static spl_vm_val_t vm_push(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_push", 2); CHECK_NARGS("vm_push", 2);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
spl_val_t val = args[1]; spl_vm_val_t val = args[1];
if (!vm) if (!vm)
return -1; return -1;
if (vm->sp >= vm->config.max_stack_depth) { if (vm->sp >= vm->config.max_stack_depth) {
@@ -311,15 +311,15 @@ static spl_val_t vm_push(int nargs, spl_val_t *args) {
* - Sets fp = sp - nargs (so arg0 = data[fp], arg1 = data[fp+1], ...) * - Sets fp = sp - nargs (so arg0 = data[fp], arg1 = data[fp+1], ...)
* - Sets ip to the function address * - Sets ip to the function address
*/ */
static spl_val_t vm_call(int nargs, spl_val_t *args) { static spl_vm_val_t vm_call(int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_call", 3); CHECK_NARGS("vm_call", 3);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0]; spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
const char *name = (const char *)(uintptr_t)args[1]; const char *name = (const char *)(uintptr_t)args[1];
spl_val_t call_nargs = args[2]; spl_vm_val_t call_nargs = args[2];
if (!vm || !name) if (!vm || !name)
return -1; return -1;
spl_func_t *func = spl_prog_get_func(vm->prog, name); spl_vm_func_t *func = spl_prog_get_func(vm->prog, name);
if (!func) { if (!func) {
fprintf(stderr, "vm_call: function '%s' not found\n", name); fprintf(stderr, "vm_call: function '%s' not found\n", name);
return -1; return -1;
@@ -358,7 +358,7 @@ SYSCALL_1(vm_run, spl_vm_t *, spl_vm_run_until(a1, 0))
* ================================================================= */ * ================================================================= */
void spl_syscall_register(spl_prog_t *prog) { void spl_syscall_register(spl_prog_t *prog) {
static spl_native_t table[] = { static spl_vm_native_t table[] = {
/* OS operations */ /* OS operations */
{"vm_exit", 0, vm_exit}, {"vm_exit", 0, vm_exit},
{"vm_putchar", 0, vm_putchar}, {"vm_putchar", 0, vm_putchar},
@@ -393,7 +393,7 @@ void spl_syscall_register(spl_prog_t *prog) {
if (!prog) if (!prog)
return; return;
vec_for(prog->natives, i) { vec_for(prog->natives, i) {
spl_native_t *nat = &vec_at(prog->natives, i); spl_vm_native_t *nat = &vec_at(prog->natives, i);
if (!nat->name || nat->impl_fn) if (!nat->name || nat->impl_fn)
continue; continue;
for (int j = 0; j < n; j++) { for (int j = 0; j < n; j++) {

View File

@@ -99,7 +99,7 @@ static int spl_type_size(spl_type_t t) {
#define PUSH(v) \ #define PUSH(v) \
do { \ do { \
spl_val_t _pv = (spl_val_t)(v); \ spl_vm_val_t _pv = (spl_vm_val_t)(v); \
if (vm->sp >= vm->config.max_stack_depth) \ if (vm->sp >= vm->config.max_stack_depth) \
VM_ERROR("stack overflow"); \ VM_ERROR("stack overflow"); \
vm->stacks.data[(vm->sp)++] = _pv; \ vm->stacks.data[(vm->sp)++] = _pv; \
@@ -121,8 +121,8 @@ static int spl_type_size(spl_type_t t) {
#define ARITH_BINOP(OP) \ #define ARITH_BINOP(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
spl_val_t _r = 0; \ spl_vm_val_t _r = 0; \
if (spl_is_float((spl_type_t)ins->type)) { \ if (spl_is_float((spl_type_t)ins->type)) { \
double _da, _db, _dr; \ double _da, _db, _dr; \
if (ins->type == SPL_F32) { \ if (ins->type == SPL_F32) { \
@@ -145,25 +145,25 @@ static int spl_type_size(spl_type_t t) {
} else { \ } else { \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
_r = (spl_val_t)((int8_t)_a OP(int8_t) _b); \ _r = (spl_vm_val_t)((int8_t)_a OP(int8_t) _b); \
break; \ break; \
case SPL_U8: \ case SPL_U8: \
_r = (spl_val_t)((uint8_t)_a OP(uint8_t) _b); \ _r = (spl_vm_val_t)((uint8_t)_a OP(uint8_t) _b); \
break; \ break; \
case SPL_I16: \ case SPL_I16: \
_r = (spl_val_t)((int16_t)_a OP(int16_t) _b); \ _r = (spl_vm_val_t)((int16_t)_a OP(int16_t) _b); \
break; \ break; \
case SPL_U16: \ case SPL_U16: \
_r = (spl_val_t)((uint16_t)_a OP(uint16_t) _b); \ _r = (spl_vm_val_t)((uint16_t)_a OP(uint16_t) _b); \
break; \ break; \
case SPL_I32: \ case SPL_I32: \
_r = (spl_val_t)((int32_t)_a OP(int32_t) _b); \ _r = (spl_vm_val_t)((int32_t)_a OP(int32_t) _b); \
break; \ break; \
case SPL_U32: \ case SPL_U32: \
_r = (spl_val_t)((uint32_t)_a OP(uint32_t) _b); \ _r = (spl_vm_val_t)((uint32_t)_a OP(uint32_t) _b); \
break; \ break; \
case SPL_I64: \ case SPL_I64: \
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_vm_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_PTR: \ case SPL_PTR: \
@@ -181,10 +181,10 @@ static int spl_type_size(spl_type_t t) {
/* signed division / remainder - all types cast to signed */ /* signed division / remainder - all types cast to signed */
#define DIV_REM_S(OP) \ #define DIV_REM_S(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
if (_b == 0) \ if (_b == 0) \
VM_ERROR("division by zero"); \ VM_ERROR("division by zero"); \
spl_val_t _r = 0; \ spl_vm_val_t _r = 0; \
if (spl_is_float((spl_type_t)ins->type)) { \ if (spl_is_float((spl_type_t)ins->type)) { \
double _da, _db, _dr; \ double _da, _db, _dr; \
if (ins->type == SPL_F32) { \ if (ins->type == SPL_F32) { \
@@ -207,31 +207,31 @@ static int spl_type_size(spl_type_t t) {
} else { \ } else { \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
_r = (spl_val_t)((int8_t)_a OP(int8_t) _b); \ _r = (spl_vm_val_t)((int8_t)_a OP(int8_t) _b); \
break; \ break; \
case SPL_U8: \ case SPL_U8: \
_r = (spl_val_t)((int8_t)_a OP(int8_t) _b); \ _r = (spl_vm_val_t)((int8_t)_a OP(int8_t) _b); \
break; \ break; \
case SPL_I16: \ case SPL_I16: \
_r = (spl_val_t)((int16_t)_a OP(int16_t) _b); \ _r = (spl_vm_val_t)((int16_t)_a OP(int16_t) _b); \
break; \ break; \
case SPL_U16: \ case SPL_U16: \
_r = (spl_val_t)((int16_t)_a OP(int16_t) _b); \ _r = (spl_vm_val_t)((int16_t)_a OP(int16_t) _b); \
break; \ break; \
case SPL_I32: \ case SPL_I32: \
_r = (spl_val_t)((int32_t)_a OP(int32_t) _b); \ _r = (spl_vm_val_t)((int32_t)_a OP(int32_t) _b); \
break; \ break; \
case SPL_U32: \ case SPL_U32: \
_r = (spl_val_t)((int32_t)_a OP(int32_t) _b); \ _r = (spl_vm_val_t)((int32_t)_a OP(int32_t) _b); \
break; \ break; \
case SPL_I64: \ case SPL_I64: \
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_vm_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_PTR: \ case SPL_PTR: \
case SPL_USIZE: \ case SPL_USIZE: \
case SPL_ISIZE: \ case SPL_ISIZE: \
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_vm_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
default: \ default: \
VM_ERROR("bad type for signed division"); \ VM_ERROR("bad type for signed division"); \
@@ -243,31 +243,31 @@ static int spl_type_size(spl_type_t t) {
/* unsigned division / remainder */ /* unsigned division / remainder */
#define DIV_REM_U(OP) \ #define DIV_REM_U(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
if (_b == 0) \ if (_b == 0) \
VM_ERROR("division by zero"); \ VM_ERROR("division by zero"); \
spl_val_t _r = 0; \ spl_vm_val_t _r = 0; \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
_r = (spl_val_t)((uint8_t)_a OP(uint8_t) _b); \ _r = (spl_vm_val_t)((uint8_t)_a OP(uint8_t) _b); \
break; \ break; \
case SPL_U8: \ case SPL_U8: \
_r = (spl_val_t)((uint8_t)_a OP(uint8_t) _b); \ _r = (spl_vm_val_t)((uint8_t)_a OP(uint8_t) _b); \
break; \ break; \
case SPL_I16: \ case SPL_I16: \
_r = (spl_val_t)((uint16_t)_a OP(uint16_t) _b); \ _r = (spl_vm_val_t)((uint16_t)_a OP(uint16_t) _b); \
break; \ break; \
case SPL_U16: \ case SPL_U16: \
_r = (spl_val_t)((uint16_t)_a OP(uint16_t) _b); \ _r = (spl_vm_val_t)((uint16_t)_a OP(uint16_t) _b); \
break; \ break; \
case SPL_I32: \ case SPL_I32: \
_r = (spl_val_t)((uint32_t)_a OP(uint32_t) _b); \ _r = (spl_vm_val_t)((uint32_t)_a OP(uint32_t) _b); \
break; \ break; \
case SPL_U32: \ case SPL_U32: \
_r = (spl_val_t)((uint32_t)_a OP(uint32_t) _b); \ _r = (spl_vm_val_t)((uint32_t)_a OP(uint32_t) _b); \
break; \ break; \
case SPL_I64: \ case SPL_I64: \
_r = (spl_val_t)((uint64_t)_a OP(uint64_t) _b); \ _r = (spl_vm_val_t)((uint64_t)_a OP(uint64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_PTR: \ case SPL_PTR: \
@@ -284,7 +284,7 @@ static int spl_type_size(spl_type_t t) {
/* CMP_ALL - equality comparisons (all types, floats via memcpy) */ /* CMP_ALL - equality comparisons (all types, floats via memcpy) */
#define CMP_ALL(OP) \ #define CMP_ALL(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
intptr_t _r = 0; \ intptr_t _r = 0; \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
@@ -338,7 +338,7 @@ static int spl_type_size(spl_type_t t) {
/* CMP_S - signed ordering (all ints cast to signed, floats OK) */ /* CMP_S - signed ordering (all ints cast to signed, floats OK) */
#define CMP_S(OP) \ #define CMP_S(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
intptr_t _r = 0; \ intptr_t _r = 0; \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
@@ -392,7 +392,7 @@ static int spl_type_size(spl_type_t t) {
/* CMP_U - unsigned ordering (all ints cast to unsigned, no float) */ /* CMP_U - unsigned ordering (all ints cast to unsigned, no float) */
#define CMP_U(OP) \ #define CMP_U(OP) \
do { \ do { \
spl_val_t _b = POP(), _a = POP(); \ spl_vm_val_t _b = POP(), _a = POP(); \
intptr_t _r = 0; \ intptr_t _r = 0; \
switch (ins->type) { \ switch (ins->type) { \
case SPL_I8: \ case SPL_I8: \
@@ -478,6 +478,7 @@ const char *ExceptionCodeToString(DWORD code) {
} }
// 全局未处理异常过滤器 // 全局未处理异常过滤器
#ifdef _WIN32
LONG WINAPI UnhandledExceptionFilterImpl(EXCEPTION_POINTERS *pExceptionInfo) { LONG WINAPI UnhandledExceptionFilterImpl(EXCEPTION_POINTERS *pExceptionInfo) {
// 获取异常记录和上下文 // 获取异常记录和上下文
PEXCEPTION_RECORD record = pExceptionInfo->ExceptionRecord; PEXCEPTION_RECORD record = pExceptionInfo->ExceptionRecord;
@@ -537,6 +538,7 @@ LONG WINAPI UnhandledExceptionFilterImpl(EXCEPTION_POINTERS *pExceptionInfo) {
// 你可以在这里调用 exit(1) 或直接返回,进程会被终止 // 你可以在这里调用 exit(1) 或直接返回,进程会被终止
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
#endif
/* ================================================================ /* ================================================================
* spl_vm_init / spl_vm_drop * spl_vm_init / spl_vm_drop
@@ -614,10 +616,10 @@ void spl_vm_skip_breakpoint(spl_vm_t *vm) {
} }
/* 前向声明(定义在文件尾部 dump 区域) */ /* 前向声明(定义在文件尾部 dump 区域) */
static const char *func_name_by_ip(spl_prog_t *prog, spl_val_t ip); static const char *func_name_by_ip(spl_prog_t *prog, spl_vm_val_t ip);
/* 函数名断点命中addr 所在函数名是否在断点表 */ /* 函数名断点命中addr 所在函数名是否在断点表 */
static int fn_breakpoint_hit(spl_vm_t *vm, spl_val_t addr) { static int fn_breakpoint_hit(spl_vm_t *vm, spl_vm_val_t addr) {
if (!vm || !vm->prog || !vec_size(vm->fn_breakpoints)) if (!vm || !vm->prog || !vec_size(vm->fn_breakpoints))
return 0; return 0;
const char *fn = func_name_by_ip(vm->prog, addr); const char *fn = func_name_by_ip(vm->prog, addr);
@@ -669,7 +671,7 @@ void spl_vm_set_debug(spl_vm_t *vm, int enabled) {
#define STACK_CANARY(vm) (vm)->stacks.data[(vm)->fp - 1] #define STACK_CANARY(vm) (vm)->stacks.data[(vm)->fp - 1]
static inline int spl_vm_call(spl_vm_t *vm, spl_val_t addr, spl_val_t nargs) { static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t nargs) {
if (vm->cp >= vm->config.max_call_depth) if (vm->cp >= vm->config.max_call_depth)
VM_ERROR("CALLI: call stack overflow"); VM_ERROR("CALLI: call stack overflow");
// spl_vm_stackdump(vm, vm->sp); // spl_vm_stackdump(vm, vm->sp);
@@ -696,7 +698,7 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
if (!vm || !vm->prog) { if (!vm || !vm->prog) {
return -1; return -1;
} }
spl_func_t *fn = spl_prog_get_func(vm->prog, entry ? entry : "main"); spl_vm_func_t *fn = spl_prog_get_func(vm->prog, entry ? entry : "main");
if (!fn) { if (!fn) {
fprintf(stderr, "vm: entry point '%s' not found\n", entry ? entry : "main"); fprintf(stderr, "vm: entry point '%s' not found\n", entry ? entry : "main");
return -1; return -1;
@@ -733,7 +735,7 @@ int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv,
* ================================================================ */ * ================================================================ */
int spl_vm_run_once(spl_vm_t *vm) { int spl_vm_run_once(spl_vm_t *vm) {
const spl_ins_t *ins; const spl_vm_ins_t *ins;
spl_prog_t *prog; spl_prog_t *prog;
if (!vm || !vm->prog) if (!vm || !vm->prog)
@@ -761,7 +763,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
if (vm->trace) { if (vm->trace) {
fprintf(stderr, "vm: ip=%zd op=%s type=%s imm=%zu sp=%zd fp=%zd\n", vm->ip - 1, fprintf(stderr, "vm: ip=%zd op=%s type=%s imm=%zu sp=%zd fp=%zd\n", vm->ip - 1,
spl_opcode_name(ins->opcode), spl_type_tag_name(ins->type), ins->imm, vm->sp, spl_vm_opcode_name(ins->opcode), spl_vm_type_kind_name(ins->type), ins->imm, vm->sp,
vm->fp); vm->fp);
} }
@@ -775,7 +777,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
case SPL_DUP: { case SPL_DUP: {
if (vm->sp < 1) if (vm->sp < 1)
VM_ERROR("DUP: stack underflow"); VM_ERROR("DUP: stack underflow");
spl_val_t _v = vm->stacks.data[vm->sp - 1]; spl_vm_val_t _v = vm->stacks.data[vm->sp - 1];
PUSH(_v); PUSH(_v);
break; break;
} }
@@ -789,7 +791,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
case SPL_SWAP: { case SPL_SWAP: {
if (vm->sp < 2) if (vm->sp < 2)
VM_ERROR("SWAP: stack underflow"); VM_ERROR("SWAP: stack underflow");
spl_val_t _t = vm->stacks.data[vm->sp - 1]; spl_vm_val_t _t = vm->stacks.data[vm->sp - 1];
vm->stacks.data[vm->sp - 1] = vm->stacks.data[vm->sp - 2]; vm->stacks.data[vm->sp - 1] = vm->stacks.data[vm->sp - 2];
vm->stacks.data[vm->sp - 2] = _t; vm->stacks.data[vm->sp - 2] = _t;
break; break;
@@ -806,9 +808,9 @@ int spl_vm_run_once(spl_vm_t *vm) {
case SPL_ROT: { case SPL_ROT: {
if (vm->sp < 3) if (vm->sp < 3)
VM_ERROR("ROT: stack underflow"); VM_ERROR("ROT: stack underflow");
spl_val_t _a = vm->stacks.data[vm->sp - 3]; spl_vm_val_t _a = vm->stacks.data[vm->sp - 3];
spl_val_t _b = vm->stacks.data[vm->sp - 2]; spl_vm_val_t _b = vm->stacks.data[vm->sp - 2];
spl_val_t _c = vm->stacks.data[vm->sp - 1]; spl_vm_val_t _c = vm->stacks.data[vm->sp - 1];
vm->stacks.data[vm->sp - 3] = _b; vm->stacks.data[vm->sp - 3] = _b;
vm->stacks.data[vm->sp - 2] = _c; vm->stacks.data[vm->sp - 2] = _c;
vm->stacks.data[vm->sp - 1] = _a; vm->stacks.data[vm->sp - 1] = _a;
@@ -840,7 +842,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
break; break;
case SPL_NEG: { case SPL_NEG: {
spl_val_t _a = POP(); spl_vm_val_t _a = POP();
if (spl_is_float((spl_type_t)ins->type)) { if (spl_is_float((spl_type_t)ins->type)) {
double _d; double _d;
if (ins->type == SPL_F32) { if (ins->type == SPL_F32) {
@@ -862,17 +864,17 @@ int spl_vm_run_once(spl_vm_t *vm) {
/* ========== Bitwise ========== */ /* ========== Bitwise ========== */
case SPL_AND: { case SPL_AND: {
spl_val_t _b = POP(), _a = POP(); spl_vm_val_t _b = POP(), _a = POP();
PUSH(_a & _b); PUSH(_a & _b);
break; break;
} }
case SPL_OR: { case SPL_OR: {
spl_val_t _b = POP(), _a = POP(); spl_vm_val_t _b = POP(), _a = POP();
PUSH(_a | _b); PUSH(_a | _b);
break; break;
} }
case SPL_XOR: { case SPL_XOR: {
spl_val_t _b = POP(), _a = POP(); spl_vm_val_t _b = POP(), _a = POP();
PUSH(_a ^ _b); PUSH(_a ^ _b);
break; break;
} }
@@ -946,8 +948,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_CALL: { case SPL_CALL: {
spl_val_t _nargs = ins->imm; spl_vm_val_t _nargs = ins->imm;
spl_val_t _addr = POP(); spl_vm_val_t _addr = POP();
int _hit = fn_breakpoint_hit(vm, _addr); int _hit = fn_breakpoint_hit(vm, _addr);
spl_vm_call(vm, _addr, _nargs); spl_vm_call(vm, _addr, _nargs);
if (_hit) if (_hit)
@@ -956,8 +958,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_CALLI: { case SPL_CALLI: {
spl_val_t _addr = POP(); spl_vm_val_t _addr = POP();
spl_val_t _nargs = POP(); spl_vm_val_t _nargs = POP();
int _hit = fn_breakpoint_hit(vm, _addr); int _hit = fn_breakpoint_hit(vm, _addr);
spl_vm_call(vm, _addr, _nargs); spl_vm_call(vm, _addr, _nargs);
if (_hit) if (_hit)
@@ -966,7 +968,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_RET: { case SPL_RET: {
spl_val_t _retval = 0; spl_vm_val_t _retval = 0;
if (ins->type != SPL_VOID) if (ins->type != SPL_VOID)
_retval = POP(); _retval = POP();
if (vm->cp <= 0) if (vm->cp <= 0)
@@ -996,7 +998,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
/* ========== Stack / Frame Local Memory ========== */ /* ========== Stack / Frame Local Memory ========== */
case SPL_ALLOC: { case SPL_ALLOC: {
spl_val_t _k = ins->imm; spl_vm_val_t _k = ins->imm;
uintptr_t _new_sp = vm->sp + _k; uintptr_t _new_sp = vm->sp + _k;
if (_new_sp > vm->config.max_stack_depth) if (_new_sp > vm->config.max_stack_depth)
VM_ERROR("ALLOC: stack overflow"); VM_ERROR("ALLOC: stack overflow");
@@ -1007,14 +1009,14 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_LADDR: case SPL_LADDR:
PUSH((spl_val_t)((char *)(vm->stacks.data + vm->fp) + ins->imm)); PUSH((spl_vm_val_t)((char *)(vm->stacks.data + vm->fp) + ins->imm));
break; break;
case SPL_GADDR: { case SPL_GADDR: {
spl_val_t _idx = ins->imm; spl_vm_val_t _idx = ins->imm;
if (_idx >= vec_size(prog->gdata)) if (_idx >= vec_size(prog->gdata))
VM_ERROR("GADDR: global data index out of range"); VM_ERROR("GADDR: global data index out of range");
PUSH((spl_val_t)(uintptr_t)vec_at(prog->gdata, _idx).data); PUSH((spl_vm_val_t)(uintptr_t)vec_at(prog->gdata, _idx).data);
break; break;
} }
@@ -1022,19 +1024,19 @@ int spl_vm_run_once(spl_vm_t *vm) {
case SPL_LOAD: { case SPL_LOAD: {
void *_addr = (void *)POP(); void *_addr = (void *)POP();
CHECK_ADDR(_addr, "LOAD"); CHECK_ADDR(_addr, "LOAD");
spl_val_t _v = 0; spl_vm_val_t _v = 0;
usize _sz = spl_type_size(ins->type); usize _sz = spl_type_size(ins->type);
memcpy(&_v, _addr, _sz); memcpy(&_v, _addr, _sz);
/* Sign-extend signed integer types smaller than 64 bits */ /* Sign-extend signed integer types smaller than 64 bits */
if (_sz > 0 && _sz < sizeof(spl_val_t) && spl_is_signed(ins->type)) { if (_sz > 0 && _sz < sizeof(spl_vm_val_t) && spl_is_signed(ins->type)) {
usize _shift = (sizeof(spl_val_t) - _sz) * 8; usize _shift = (sizeof(spl_vm_val_t) - _sz) * 8;
_v = (spl_val_t)(((isize)(_v << _shift)) >> _shift); _v = (spl_vm_val_t)(((isize)(_v << _shift)) >> _shift);
} }
PUSH(_v); PUSH(_v);
break; break;
} }
case SPL_STORE: { case SPL_STORE: {
spl_val_t _v = POP(); spl_vm_val_t _v = POP();
void *_addr = (void *)POP(); void *_addr = (void *)POP();
CHECK_ADDR(_addr, "STORE"); CHECK_ADDR(_addr, "STORE");
memcpy(_addr, &_v, spl_type_size(ins->type)); memcpy(_addr, &_v, spl_type_size(ins->type));
@@ -1043,12 +1045,12 @@ int spl_vm_run_once(spl_vm_t *vm) {
/* ========== Type Conversion ========== */ /* ========== Type Conversion ========== */
case SPL_TRUNC: { case SPL_TRUNC: {
spl_val_t _v = POP(); spl_vm_val_t _v = POP();
intptr_t _bits = ins->imm; intptr_t _bits = ins->imm;
if (_bits < 1 || _bits > 64) if (_bits < 1 || _bits > 64)
VM_ERROR("TRUNC: bad bit-width"); VM_ERROR("TRUNC: bad bit-width");
if (_bits < 64) { if (_bits < 64) {
spl_val_t _mask = ((spl_val_t)1 << _bits) - 1; spl_vm_val_t _mask = ((spl_vm_val_t)1 << _bits) - 1;
_v &= _mask; _v &= _mask;
} }
PUSH(_v); PUSH(_v);
@@ -1056,13 +1058,13 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_SEXT: { case SPL_SEXT: {
spl_val_t _v = POP(); spl_vm_val_t _v = POP();
intptr_t _bits = ins->imm; intptr_t _bits = ins->imm;
if (_bits < 1 || _bits > 64) if (_bits < 1 || _bits > 64)
VM_ERROR("SEXT: bad bit-width"); VM_ERROR("SEXT: bad bit-width");
if (_bits < 64) { if (_bits < 64) {
spl_val_t _sign = (spl_val_t)1 << (_bits - 1); spl_vm_val_t _sign = (spl_vm_val_t)1 << (_bits - 1);
spl_val_t _mask = ((spl_val_t)1 << _bits) - 1; spl_vm_val_t _mask = ((spl_vm_val_t)1 << _bits) - 1;
_v &= _mask; _v &= _mask;
if (_v & _sign) if (_v & _sign)
_v |= ~_mask; _v |= ~_mask;
@@ -1072,12 +1074,12 @@ int spl_vm_run_once(spl_vm_t *vm) {
} }
case SPL_ZEXT: { case SPL_ZEXT: {
spl_val_t _v = POP(); spl_vm_val_t _v = POP();
intptr_t _bits = ins->imm; intptr_t _bits = ins->imm;
if (_bits < 1 || _bits > 64) if (_bits < 1 || _bits > 64)
VM_ERROR("ZEXT: bad bit-width"); VM_ERROR("ZEXT: bad bit-width");
if (_bits < 64) if (_bits < 64)
_v &= ((spl_val_t)1 << _bits) - 1; _v &= ((spl_vm_val_t)1 << _bits) - 1;
PUSH(_v); PUSH(_v);
break; break;
} }
@@ -1085,8 +1087,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
/* ========== Native Interface ========== */ /* ========== Native Interface ========== */
case SPL_NCALL: { case SPL_NCALL: {
intptr_t _nargs = ins->imm; intptr_t _nargs = ins->imm;
spl_val_t _nat_idx = POP(); spl_vm_val_t _nat_idx = POP();
spl_native_t *_nat; spl_vm_native_t *_nat;
if (_nat_idx >= vec_size(prog->natives)) if (_nat_idx >= vec_size(prog->natives))
VM_ERROR("NCALL: native index out of range"); VM_ERROR("NCALL: native index out of range");
_nat = &vec_at(prog->natives, _nat_idx); _nat = &vec_at(prog->natives, _nat_idx);
@@ -1095,18 +1097,18 @@ int spl_vm_run_once(spl_vm_t *vm) {
"NCALL: NULL native function pointer expect %s", _nat->name); "NCALL: NULL native function pointer expect %s", _nat->name);
VM_ERROR(vm->error_msg); VM_ERROR(vm->error_msg);
} }
spl_val_t *_arg_base = vm->stacks.data + vm->sp - _nargs; spl_vm_val_t *_arg_base = vm->stacks.data + vm->sp - _nargs;
// spl_vm_stackdump(vm, vm->sp); // spl_vm_stackdump(vm, vm->sp);
// printf("addr %p nargs %zd sp %zd stack %p arg_base %p\n", _nat->impl_fn, _nargs, vm->sp, // printf("addr %p nargs %zd sp %zd stack %p arg_base %p\n", _nat->impl_fn, _nargs, vm->sp,
// vm->stacks.data, _arg_base); // vm->stacks.data, _arg_base);
spl_val_t _result = _nat->impl_fn(_nargs, _arg_base); spl_vm_val_t _result = _nat->impl_fn(_nargs, _arg_base);
vm->sp -= _nargs; vm->sp -= _nargs;
PUSH(_result); PUSH(_result);
break; break;
} }
case SPL_NLIB: { case SPL_NLIB: {
spl_val_t _si = ins->imm; spl_vm_val_t _si = ins->imm;
const char *_lib; const char *_lib;
if (_si >= vec_size(prog->strtab) || !vec_at(prog->strtab, _si)) if (_si >= vec_size(prog->strtab) || !vec_at(prog->strtab, _si))
VM_ERROR("NLIB: invalid string index"); VM_ERROR("NLIB: invalid string index");
@@ -1175,44 +1177,44 @@ int spl_vm_run_until(spl_vm_t *vm, size_t step) {
} }
} }
static const char *func_name_by_ip(spl_prog_t *prog, spl_val_t ip) { static const char *func_name_by_ip(spl_prog_t *prog, spl_vm_val_t ip) {
vec_for(prog->funcs, i) { vec_for(prog->funcs, i) {
spl_func_t *f = &vec_at(prog->funcs, i); spl_vm_func_t *f = &vec_at(prog->funcs, i);
if (ip >= f->address && ip < (f->address + f->ninsns)) if (ip >= f->address && ip < (f->address + f->ninsns))
return f->name; return f->name;
} }
return "?"; return "?";
} }
void spl_vm_dump_instr(spl_vm_t *vm, spl_val_t ip) { void spl_vm_dump_instr(spl_vm_t *vm, spl_vm_val_t ip) {
if (!vm || !vm->prog) if (!vm || !vm->prog)
return; return;
if (ip >= vec_size(vm->prog->insns)) if (ip >= vec_size(vm->prog->insns))
return; return;
spl_ins_t *ins = &vec_at(vm->prog->insns, ip); spl_vm_ins_t *ins = &vec_at(vm->prog->insns, ip);
fprintf(stderr, " instr at ip=%zd: op=%s type=%s imm=%zu\n", ip, spl_opcode_name(ins->opcode), fprintf(stderr, " instr at ip=%zd: op=%s type=%s imm=%zu\n", ip,
spl_type_tag_name(ins->type), ins->imm); spl_vm_opcode_name(ins->opcode), spl_vm_type_kind_name(ins->type), ins->imm);
} }
void spl_vm_stackdump(spl_vm_t *vm, spl_val_t sp) { void spl_vm_stackdump(spl_vm_t *vm, spl_vm_val_t sp) {
if (!vm) if (!vm)
return; return;
fprintf(stderr, "stack dump (sp=%zd, fp=%zd):\n", sp, vm->fp); fprintf(stderr, "stack dump (sp=%zd, fp=%zd):\n", sp, vm->fp);
spl_val_t start = sp > 32 ? sp - 32 : 0; spl_vm_val_t start = sp > 32 ? sp - 32 : 0;
for (spl_val_t i = start; i <= sp; i++) { for (spl_vm_val_t i = start; i <= sp; i++) {
fprintf(stderr, " [%3zd] = [addr 0x%p] 0x%016zx (%zd)\n", i, &vm->stacks.data[i], fprintf(stderr, " [%3zd] = [addr 0x%p] 0x%016zx (%zd)\n", i, &vm->stacks.data[i],
vm->stacks.data[i], vm->stacks.data[i]); vm->stacks.data[i], vm->stacks.data[i]);
} }
} }
int spl_vm_backtrace(spl_vm_t *vm, spl_val_t fp) { int spl_vm_backtrace(spl_vm_t *vm, spl_vm_val_t fp) {
if (!vm || !vm->prog) if (!vm || !vm->prog)
return -1; return -1;
(void)fp; (void)fp;
fprintf(stderr, "backtrace: \n"); fprintf(stderr, "backtrace: \n");
for (isize i = vm->cp - 1; i >= 0; i--) { for (isize i = vm->cp - 1; i >= 0; i--) {
spl_val_t _saved_ip = vm->frames.data[i].saved_ip; spl_vm_val_t _saved_ip = vm->frames.data[i].saved_ip;
spl_val_t _saved_fp = vm->frames.data[i].saved_fp; spl_vm_val_t _saved_fp = vm->frames.data[i].saved_fp;
const char *_fn = func_name_by_ip(vm->prog, _saved_ip - 1); const char *_fn = func_name_by_ip(vm->prog, _saved_ip - 1);
fprintf(stderr, " [%3zd] %s (fp=%zd, ip=%zd, args=%zd)\n", i, _fn, _saved_fp, _saved_ip, fprintf(stderr, " [%3zd] %s (fp=%zd, ip=%zd, args=%zd)\n", i, _fn, _saved_fp, _saved_ip,
vm->frames.data[i].nargs); vm->frames.data[i].nargs);

View File

@@ -7,16 +7,16 @@
#include "spl_mcode.h" #include "spl_mcode.h"
#include <stdint.h> #include <stdint.h>
#define SPL_STACK_CANARY ((spl_val_t)0xDEADBEEFCAFEBABEull) #define SPL_STACK_CANARY ((spl_vm_val_t)0xDEADBEEFCAFEBABEull)
typedef struct { typedef struct {
uintptr_t saved_sp; uintptr_t saved_sp;
uintptr_t saved_fp; uintptr_t saved_fp;
uintptr_t saved_ip; uintptr_t saved_ip;
spl_val_t nargs; spl_vm_val_t nargs;
} spl_callframe_t; } spl_callframe_t;
typedef VEC(spl_val_t) spl_stack_vec_t; typedef VEC(spl_vm_val_t) spl_stack_vec_t;
typedef VEC(spl_callframe_t) spl_frame_vec_t; typedef VEC(spl_callframe_t) spl_frame_vec_t;
typedef struct { typedef struct {
@@ -71,8 +71,8 @@ void spl_vm_clear_breakpoints(spl_vm_t *vm);
/* 让 run_once 执行当前指令忽略一次断点命中continue 越过当前断点用 */ /* 让 run_once 执行当前指令忽略一次断点命中continue 越过当前断点用 */
void spl_vm_skip_breakpoint(spl_vm_t *vm); void spl_vm_skip_breakpoint(spl_vm_t *vm);
void spl_vm_dump_instr(spl_vm_t *vm, spl_val_t ip); void spl_vm_dump_instr(spl_vm_t *vm, spl_vm_val_t ip);
void spl_vm_stackdump(spl_vm_t *vm, spl_val_t sp); void spl_vm_stackdump(spl_vm_t *vm, spl_vm_val_t sp);
int spl_vm_backtrace(spl_vm_t *vm, spl_val_t fp); int spl_vm_backtrace(spl_vm_t *vm, spl_vm_val_t fp);
#endif /* __SPL_VM_H__ */ #endif /* __SPL_VM_H__ */

View File

@@ -20,7 +20,7 @@
#define LE64(p, v) \ #define LE64(p, v) \
do { \ do { \
unsigned char *_p = (p); \ unsigned char *_p = (p); \
spl_val_t _v = (spl_val_t)(v); \ spl_vm_val_t _v = (spl_vm_val_t)(v); \
*_p++ = (unsigned char)(_v); \ *_p++ = (unsigned char)(_v); \
*_p++ = (unsigned char)(_v >> 8); \ *_p++ = (unsigned char)(_v >> 8); \
*_p++ = (unsigned char)(_v >> 16); \ *_p++ = (unsigned char)(_v >> 16); \
@@ -33,8 +33,8 @@
} while (0) } while (0)
/* Convenience: build spl_ins_t from raw fields */ /* Convenience: build spl_ins_t from raw fields */
static spl_ins_t ins(uint16_t op, uint16_t type, spl_val_t imm) { static spl_vm_ins_t ins(uint16_t op, uint16_t type, spl_vm_val_t imm) {
spl_ins_t x; spl_vm_ins_t x;
x.opcode = op; x.opcode = op;
x.type = type; x.type = type;
x.imm = imm; x.imm = imm;
@@ -43,8 +43,8 @@ static spl_ins_t ins(uint16_t op, uint16_t type, spl_val_t imm) {
/* Build a single-function SIR binary in malloc'd memory. /* Build a single-function SIR binary in malloc'd memory.
* Returns buffer that must be freed by caller. */ * Returns buffer that must be freed by caller. */
static unsigned char *build_binary(const char *fname, spl_val_t nargs, const spl_ins_t *instns, static unsigned char *build_binary(const char *fname, spl_vm_val_t nargs,
int ninsns, size_t *out_len) { const spl_vm_ins_t *instns, int ninsns, size_t *out_len) {
size_t nlen = strlen(fname) + 1; size_t nlen = strlen(fname) + 1;
size_t npad = ((nlen + 7) / 8) * 8 - nlen; size_t npad = ((nlen + 7) / 8) * 8 - nlen;
size_t sz = 8 + 8 + 8 + 8 + 8 + 8 /* magic + 5 counts */ size_t sz = 8 + 8 + 8 + 8 + 8 + 8 /* magic + 5 counts */
@@ -56,20 +56,20 @@ static unsigned char *build_binary(const char *fname, spl_val_t nargs, const spl
memcpy(p, "SPLBIN\0\0", 8); memcpy(p, "SPLBIN\0\0", 8);
p += 8; /* magic */ p += 8; /* magic */
LE64(p, 1); /* nfuncs */ LE64(p, 1); /* nfuncs */
LE64(p, (spl_val_t)ninsns); /* ninsns */ LE64(p, (spl_vm_val_t)ninsns); /* ninsns */
LE64(p, 0); /* nnatives */ LE64(p, 0); /* nnatives */
LE64(p, 0); /* nstrs */ LE64(p, 0); /* nstrs */
LE64(p, 0); /* ndata */ LE64(p, 0); /* ndata */
/* func entry */ /* func entry */
LE64(p, (spl_val_t)nlen); /* name_len */ LE64(p, (spl_vm_val_t)nlen); /* name_len */
memcpy(p, fname, nlen); memcpy(p, fname, nlen);
p += nlen; p += nlen;
memset(p, 0, npad); memset(p, 0, npad);
p += npad; p += npad;
LE64(p, 0); /* idx_of_strtab */ LE64(p, 0); /* idx_of_strtab */
LE64(p, nargs); LE64(p, nargs);
LE64(p, (spl_val_t)ninsns); LE64(p, (spl_vm_val_t)ninsns);
LE64(p, 0); /* address = 0 */ LE64(p, 0); /* address = 0 */
for (int i = 0; i < ninsns; i++) { for (int i = 0; i < ninsns; i++) {
@@ -101,7 +101,7 @@ static int write_temp(const unsigned char *bin, size_t len) {
} }
/* Run a single-function program, return exit code (or -1 on failure). */ /* Run a single-function program, return exit code (or -1 on failure). */
static int run(const spl_ins_t *instns, int ninsns) { static int run(const spl_vm_ins_t *instns, int ninsns) {
size_t len; size_t len;
unsigned char *bin = build_binary("main", 0, instns, ninsns, &len); unsigned char *bin = build_binary("main", 0, instns, ninsns, &len);
spl_prog_t prog; spl_prog_t prog;
@@ -127,7 +127,7 @@ static int run(const spl_ins_t *instns, int ninsns) {
} }
/* Run with native functions registered. */ /* Run with native functions registered. */
static int run_with_natives(const spl_ins_t *instns, int ninsns, spl_native_t *natives, static int run_with_natives(const spl_vm_ins_t *instns, int ninsns, spl_vm_native_t *natives,
int nnatives) { int nnatives) {
size_t len; size_t len;
unsigned char *bin = build_binary("main", 0, instns, ninsns, &len); unsigned char *bin = build_binary("main", 0, instns, ninsns, &len);
@@ -159,7 +159,7 @@ static int run_with_natives(const spl_ins_t *instns, int ninsns, spl_native_t *n
* Native function for NCALL tests * Native function for NCALL tests
* ================================================================ */ * ================================================================ */
static spl_val_t native_add_impl(int nargs, spl_val_t *args) { static spl_vm_val_t native_add_impl(int nargs, spl_vm_val_t *args) {
return (nargs >= 2) ? args[0] + args[1] : 0; return (nargs >= 2) ? args[0] + args[1] : 0;
} }
@@ -168,24 +168,24 @@ static spl_val_t native_add_impl(int nargs, spl_val_t *args) {
* ================================================================ */ * ================================================================ */
void test_push_imm(void) { void test_push_imm(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_RET, SPL_I32, 0)}; spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 2) == 42); TEST_CHECK(run(p, 2) == 42);
} }
void test_dup(void) { void test_dup(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 99), ins(SPL_DUP, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 99), ins(SPL_DUP, SPL_VOID, 0),
ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 198); TEST_CHECK(run(p, 4) == 198);
} }
void test_drop(void) { void test_drop(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2),
ins(SPL_DROP, SPL_VOID, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_DROP, SPL_VOID, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_swap(void) { void test_swap(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2),
ins(SPL_SWAP, SPL_VOID, 0), ins(SPL_DROP, SPL_VOID, 0), ins(SPL_SWAP, SPL_VOID, 0), ins(SPL_DROP, SPL_VOID, 0),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 5) == 2); TEST_CHECK(run(p, 5) == 2);
@@ -193,7 +193,7 @@ void test_swap(void) {
void test_pick(void) { void test_pick(void) {
/* push 10, 20, 30, pick 1 -> copy 20, add -> 50 */ /* push 10, 20, 30, pick 1 -> copy 20, add -> 50 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20),
ins(SPL_PUSH, SPL_I32, 30), ins(SPL_PICK, SPL_VOID, 1), ins(SPL_PUSH, SPL_I32, 30), ins(SPL_PICK, SPL_VOID, 1),
ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 6) == 50); TEST_CHECK(run(p, 6) == 50);
@@ -204,43 +204,43 @@ void test_pick(void) {
* ================================================================ */ * ================================================================ */
void test_add(void) { void test_add(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 2), ins(SPL_PUSH, SPL_I32, 3), ins(SPL_ADD, SPL_I32, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 2), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 5); TEST_CHECK(run(p, 4) == 5);
} }
void test_sub(void) { void test_sub(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 3), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_SUB, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_SUB, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 7); TEST_CHECK(run(p, 4) == 7);
} }
void test_mul(void) { void test_mul(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 6), ins(SPL_PUSH, SPL_I32, 7), ins(SPL_MUL, SPL_I32, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 6), ins(SPL_PUSH, SPL_I32, 7),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_MUL, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 42); TEST_CHECK(run(p, 4) == 42);
} }
void test_div(void) { void test_div(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 100), ins(SPL_PUSH, SPL_I32, 3), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 100), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_DIV_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_DIV_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 33); TEST_CHECK(run(p, 4) == 33);
} }
void test_rem(void) { void test_rem(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 100), ins(SPL_PUSH, SPL_I32, 3), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 100), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_REM_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_REM_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_neg(void) { void test_neg(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_NEG, SPL_I32, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_NEG, SPL_I32, 0),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 3) == -42); TEST_CHECK(run(p, 3) == -42);
} }
void test_i64_arith(void) { void test_i64_arith(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I64, 42), ins(SPL_RET, SPL_I64, 0)}; spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I64, 42), ins(SPL_RET, SPL_I64, 0)};
TEST_CHECK(run(p, 2) == 42); TEST_CHECK(run(p, 2) == 42);
} }
@@ -249,45 +249,46 @@ void test_i64_arith(void) {
* ================================================================ */ * ================================================================ */
void test_and(void) { void test_and(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFF00), ins(SPL_PUSH, SPL_U32, 0x0FF0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFF00), ins(SPL_PUSH, SPL_U32, 0x0FF0),
ins(SPL_AND, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_AND, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 0x0F00); TEST_CHECK(run(p, 4) == 0x0F00);
} }
void test_or(void) { void test_or(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFF00), ins(SPL_PUSH, SPL_U32, 0x00FF), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFF00), ins(SPL_PUSH, SPL_U32, 0x00FF),
ins(SPL_OR, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_OR, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 0xFFFF); TEST_CHECK(run(p, 4) == 0xFFFF);
} }
void test_xor(void) { void test_xor(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF), ins(SPL_PUSH, SPL_U32, 0x0FF0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF), ins(SPL_PUSH, SPL_U32, 0x0FF0),
ins(SPL_XOR, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_XOR, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 0xF00F); TEST_CHECK(run(p, 4) == 0xF00F);
} }
void test_not(void) { void test_not(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF0000), ins(SPL_NOT, SPL_U32, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF0000), ins(SPL_NOT, SPL_U32, 0),
ins(SPL_RET, SPL_U32, 0)}; ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 3) == (unsigned int)0x0000FFFF); TEST_CHECK(run(p, 3) == (unsigned int)0x0000FFFF);
} }
void test_shl(void) { void test_shl(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 1), ins(SPL_PUSH, SPL_U32, 10), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 1), ins(SPL_PUSH, SPL_U32, 10),
ins(SPL_SHL, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_SHL, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1024); TEST_CHECK(run(p, 4) == 1024);
} }
void test_shr(void) { void test_shr(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 1024), ins(SPL_PUSH, SPL_U32, 10), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 1024), ins(SPL_PUSH, SPL_U32, 10),
ins(SPL_SHR_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_SHR_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_shr_s(void) { void test_shr_s(void) {
/* arithmetic right shift: -1024 >> 5 sign-extends */ /* arithmetic right shift: -1024 >> 5 sign-extends */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, (spl_val_t)(int32_t)-1024), ins(SPL_PUSH, SPL_U32, 5), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, (spl_vm_val_t)(int32_t)-1024),
ins(SPL_SHR_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_PUSH, SPL_U32, 5), ins(SPL_SHR_S, SPL_I32, 0),
ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == -32); TEST_CHECK(run(p, 4) == -32);
} }
@@ -296,68 +297,68 @@ void test_shr_s(void) {
* ================================================================ */ * ================================================================ */
void test_eq(void) { void test_eq(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_PUSH, SPL_I32, 42), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_PUSH, SPL_I32, 42),
ins(SPL_EQ, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_EQ, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_neq(void) { void test_neq(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_PUSH, SPL_I32, 99), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 42), ins(SPL_PUSH, SPL_I32, 99),
ins(SPL_NE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_NE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_lt(void) { void test_lt(void) {
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20),
ins(SPL_SLT, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_SLT, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_gt_signed(void) { void test_gt_signed(void) {
/* -1 > 1 should be 0 (false) for signed compare */ /* -1 > 1 should be 0 (false) for signed compare */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1),
ins(SPL_SGT, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_SGT, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 0); TEST_CHECK(run(p, 4) == 0);
} }
void test_sle(void) { void test_sle(void) {
/* -1 <= 1 -> true (1) for signed */ /* -1 <= 1 -> true (1) for signed */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1),
ins(SPL_SLE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_SLE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_sge(void) { void test_sge(void) {
/* -1 >= 1 -> false (0) for signed */ /* -1 >= 1 -> false (0) for signed */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_I32, 1),
ins(SPL_SGE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_SGE, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 4) == 0); TEST_CHECK(run(p, 4) == 0);
} }
void test_ult(void) { void test_ult(void) {
/* 0xFFFFFFFF < 1 -> false (0) for unsigned */ /* 0xFFFFFFFF < 1 -> false (0) for unsigned */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1),
ins(SPL_ULT, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_ULT, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 0); TEST_CHECK(run(p, 4) == 0);
} }
void test_ule(void) { void test_ule(void) {
/* 0xFFFFFFFF <= 0xFFFFFFFF -> true (1) */ /* 0xFFFFFFFF <= 0xFFFFFFFF -> true (1) */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF),
ins(SPL_ULE, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_ULE, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_ugt(void) { void test_ugt(void) {
/* 0xFFFFFFFF > 1 -> true (1) for unsigned */ /* 0xFFFFFFFF > 1 -> true (1) for unsigned */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1),
ins(SPL_UGT, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_UGT, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
void test_uge(void) { void test_uge(void) {
/* 0xFFFFFFFF >= 1 -> true (1) */ /* 0xFFFFFFFF >= 1 -> true (1) */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFFFFFF), ins(SPL_PUSH, SPL_U32, 1),
ins(SPL_UGE, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_UGE, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
@@ -369,7 +370,7 @@ void test_uge(void) {
void test_jmp(void) { void test_jmp(void) {
/* push 1, jmp +3 (skip next 2 insns), push 2 (skipped), push 3, add, ret -> 4 */ /* push 1, jmp +3 (skip next 2 insns), push 2 (skipped), push 3, add, ret -> 4 */
/* jmp at ip=1, after fetch ip=2, target ip=3 (push 3) => offset = 1 */ /* jmp at ip=1, after fetch ip=2, target ip=3 (push 3) => offset = 1 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_JMP, SPL_VOID, 1), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_JMP, SPL_VOID, 1),
ins(SPL_PUSH, SPL_I32, 2), ins(SPL_PUSH, SPL_I32, 3), ins(SPL_PUSH, SPL_I32, 2), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 6) == 4); TEST_CHECK(run(p, 6) == 4);
@@ -377,13 +378,13 @@ void test_jmp(void) {
void test_bz_bnz(void) { void test_bz_bnz(void) {
/* push 0, bz +2 (skip to ret with 1) -> return 1 */ /* push 0, bz +2 (skip to ret with 1) -> return 1 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0), ins(SPL_BZ, SPL_VOID, 2), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0), ins(SPL_BZ, SPL_VOID, 2),
ins(SPL_PUSH, SPL_I32, 99), ins(SPL_RET, SPL_I32, 0), ins(SPL_PUSH, SPL_I32, 99), ins(SPL_RET, SPL_I32, 0),
ins(SPL_PUSH, SPL_I32, 1), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_PUSH, SPL_I32, 1), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 6) == 1); TEST_CHECK(run(p, 6) == 1);
/* push 1, bnz +2 (skip to ret with 42) -> return 42 */ /* push 1, bnz +2 (skip to ret with 42) -> return 42 */
spl_ins_t q[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_BNZ, SPL_VOID, 2), spl_vm_ins_t q[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_BNZ, SPL_VOID, 2),
ins(SPL_PUSH, SPL_I32, 99), ins(SPL_RET, SPL_I32, 0), ins(SPL_PUSH, SPL_I32, 99), ins(SPL_RET, SPL_I32, 0),
ins(SPL_PUSH, SPL_I32, 42), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_PUSH, SPL_I32, 42), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(q, 6) == 42); TEST_CHECK(run(q, 6) == 42);
@@ -395,7 +396,7 @@ void test_bz_bnz(void) {
void test_alloc_laddr_st64_ld64(void) { void test_alloc_laddr_st64_ld64(void) {
/* alloc 1 local, laddr + st64 42, laddr + ld64 back -> 42 */ /* alloc 1 local, laddr + st64 42, laddr + ld64 back -> 42 */
spl_ins_t p[] = { spl_vm_ins_t p[] = {
ins(SPL_ALLOC, SPL_VOID, 1), /* 0: alloc 1 local */ ins(SPL_ALLOC, SPL_VOID, 1), /* 0: alloc 1 local */
ins(SPL_LADDR, SPL_VOID, 0), /* 1: addr of local[0] */ ins(SPL_LADDR, SPL_VOID, 0), /* 1: addr of local[0] */
ins(SPL_PUSH, SPL_I64, 42), /* 2: value */ ins(SPL_PUSH, SPL_I64, 42), /* 2: value */
@@ -409,7 +410,7 @@ void test_alloc_laddr_st64_ld64(void) {
void test_alloc_zeroed(void) { void test_alloc_zeroed(void) {
/* alloc 1 local, laddr + ld64 -> should be 0 (zero-initialized) */ /* alloc 1 local, laddr + ld64 -> should be 0 (zero-initialized) */
spl_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 1), ins(SPL_LADDR, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 1), ins(SPL_LADDR, SPL_VOID, 0),
ins(SPL_LOAD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)}; ins(SPL_LOAD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)};
TEST_CHECK(run(p, 4) == 0); TEST_CHECK(run(p, 4) == 0);
} }
@@ -420,7 +421,7 @@ void test_alloc_zeroed(void) {
void test_ld_st64(void) { void test_ld_st64(void) {
/* alloc 8 slots, st64 42, ld64 back -> 42 */ /* alloc 8 slots, st64 42, ld64 back -> 42 */
spl_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0),
ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 42), ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 42),
ins(SPL_STORE, SPL_I64, 0), ins(SPL_LOAD, SPL_I64, 0), ins(SPL_STORE, SPL_I64, 0), ins(SPL_LOAD, SPL_I64, 0),
ins(SPL_RET, SPL_I64, 0)}; ins(SPL_RET, SPL_I64, 0)};
@@ -428,7 +429,7 @@ void test_ld_st64(void) {
} }
void test_ld_st32(void) { void test_ld_st32(void) {
spl_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0),
ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xAABBCCDD), ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xAABBCCDD),
ins(SPL_STORE, SPL_U32, 0), ins(SPL_LOAD, SPL_U32, 0), ins(SPL_STORE, SPL_U32, 0), ins(SPL_LOAD, SPL_U32, 0),
ins(SPL_RET, SPL_U32, 0)}; ins(SPL_RET, SPL_U32, 0)};
@@ -436,7 +437,7 @@ void test_ld_st32(void) {
} }
void test_ld_st16(void) { void test_ld_st16(void) {
spl_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0),
ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xBEEF), ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xBEEF),
ins(SPL_STORE, SPL_U16, 0), ins(SPL_LOAD, SPL_U16, 0), ins(SPL_STORE, SPL_U16, 0), ins(SPL_LOAD, SPL_U16, 0),
ins(SPL_RET, SPL_U16, 0)}; ins(SPL_RET, SPL_U16, 0)};
@@ -444,7 +445,7 @@ void test_ld_st16(void) {
} }
void test_ld_st8(void) { void test_ld_st8(void) {
spl_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0), spl_vm_ins_t p[] = {ins(SPL_ALLOC, SPL_VOID, 8), ins(SPL_LADDR, SPL_VOID, 0),
ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xAB), ins(SPL_DUP, SPL_VOID, 0), ins(SPL_PUSH, SPL_I64, 0xAB),
ins(SPL_STORE, SPL_U8, 0), ins(SPL_LOAD, SPL_U8, 0), ins(SPL_STORE, SPL_U8, 0), ins(SPL_LOAD, SPL_U8, 0),
ins(SPL_RET, SPL_U8, 0)}; ins(SPL_RET, SPL_U8, 0)};
@@ -475,10 +476,10 @@ void test_call_add(void) {
* call 2 ip=9 nargs=2 * call 2 ip=9 nargs=2
* ret i64 ip=10 * ret i64 ip=10
*/ */
spl_ins_t add_insns[] = {ins(SPL_LADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_I64, 0), spl_vm_ins_t add_insns[] = {ins(SPL_LADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_I64, 0),
ins(SPL_LADDR, SPL_VOID, 8), ins(SPL_LOAD, SPL_I64, 0), ins(SPL_LADDR, SPL_VOID, 8), ins(SPL_LOAD, SPL_I64, 0),
ins(SPL_ADD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)}; ins(SPL_ADD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)};
spl_ins_t main_insns[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20), spl_vm_ins_t main_insns[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20),
ins(SPL_PUSH, SPL_VOID, 0), ins(SPL_CALL, SPL_VOID, 2), ins(SPL_PUSH, SPL_VOID, 0), ins(SPL_CALL, SPL_VOID, 2),
ins(SPL_RET, SPL_I64, 0)}; ins(SPL_RET, SPL_I64, 0)};
@@ -499,32 +500,32 @@ void test_call_add(void) {
memcpy(p, "SPLBIN\0\0", 8); memcpy(p, "SPLBIN\0\0", 8);
p += 8; p += 8;
LE64(p, 2); LE64(p, 2);
LE64(p, (spl_val_t)ninsns_t); LE64(p, (spl_vm_val_t)ninsns_t);
LE64(p, 0); LE64(p, 0);
LE64(p, 0); LE64(p, 0);
LE64(p, 0); LE64(p, 0);
/* func[0]: "add" */ /* func[0]: "add" */
LE64(p, (spl_val_t)nlen0); LE64(p, (spl_vm_val_t)nlen0);
memcpy(p, "add", nlen0); memcpy(p, "add", nlen0);
p += nlen0; p += nlen0;
memset(p, 0, npad0); memset(p, 0, npad0);
p += npad0; p += npad0;
LE64(p, 0); LE64(p, 0);
LE64(p, 2); LE64(p, 2);
LE64(p, (spl_val_t)nadd); LE64(p, (spl_vm_val_t)nadd);
LE64(p, 0); LE64(p, 0);
/* func[1]: "main" */ /* func[1]: "main" */
LE64(p, (spl_val_t)nlen1); LE64(p, (spl_vm_val_t)nlen1);
memcpy(p, "main", nlen1); memcpy(p, "main", nlen1);
p += nlen1; p += nlen1;
memset(p, 0, npad1); memset(p, 0, npad1);
p += npad1; p += npad1;
LE64(p, 0); LE64(p, 0);
LE64(p, 0); LE64(p, 0);
LE64(p, (spl_val_t)nmain); LE64(p, (spl_vm_val_t)nmain);
LE64(p, (spl_val_t)nadd); /* address */ LE64(p, (spl_vm_val_t)nadd); /* address */
for (int i = 0; i < nadd; i++) { for (int i = 0; i < nadd; i++) {
*p++ = (unsigned char)(add_insns[i].opcode); *p++ = (unsigned char)(add_insns[i].opcode);
@@ -582,10 +583,10 @@ void test_calli(void) {
* calli ip=10 * calli ip=10
* ret i64 ip=11 * ret i64 ip=11
*/ */
spl_ins_t add_insns[] = {ins(SPL_LADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_I64, 0), spl_vm_ins_t add_insns[] = {ins(SPL_LADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_I64, 0),
ins(SPL_LADDR, SPL_VOID, 8), ins(SPL_LOAD, SPL_I64, 0), ins(SPL_LADDR, SPL_VOID, 8), ins(SPL_LOAD, SPL_I64, 0),
ins(SPL_ADD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)}; ins(SPL_ADD, SPL_I64, 0), ins(SPL_RET, SPL_I64, 0)};
spl_ins_t main_insns[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20), spl_vm_ins_t main_insns[] = {ins(SPL_PUSH, SPL_I32, 10), ins(SPL_PUSH, SPL_I32, 20),
ins(SPL_PUSH, SPL_VOID, 2), ins(SPL_PUSH, SPL_VOID, 0), ins(SPL_PUSH, SPL_VOID, 2), ins(SPL_PUSH, SPL_VOID, 0),
ins(SPL_CALLI, SPL_VOID, 0), ins(SPL_RET, SPL_I64, 0)}; ins(SPL_CALLI, SPL_VOID, 0), ins(SPL_RET, SPL_I64, 0)};
@@ -602,13 +603,13 @@ void test_calli(void) {
memcpy(p, "SPLBIN\0\0", 8); memcpy(p, "SPLBIN\0\0", 8);
p += 8; p += 8;
LE64(p, 2); LE64(p, 2);
LE64(p, (spl_val_t)ninsns_t); LE64(p, (spl_vm_val_t)ninsns_t);
LE64(p, 0); LE64(p, 0);
LE64(p, 0); LE64(p, 0);
LE64(p, 0); LE64(p, 0);
/* func[0]: add */ /* func[0]: add */
LE64(p, (spl_val_t)nlen0); LE64(p, (spl_vm_val_t)nlen0);
memcpy(p, "add", nlen0); memcpy(p, "add", nlen0);
p += nlen0; p += nlen0;
memset(p, 0, npad0); memset(p, 0, npad0);
@@ -619,7 +620,7 @@ void test_calli(void) {
LE64(p, 0); LE64(p, 0);
/* func[1]: main */ /* func[1]: main */
LE64(p, (spl_val_t)nlen1); LE64(p, (spl_vm_val_t)nlen1);
memcpy(p, "main", nlen1); memcpy(p, "main", nlen1);
p += nlen1; p += nlen1;
memset(p, 0, npad1); memset(p, 0, npad1);
@@ -669,7 +670,7 @@ void test_calli(void) {
void test_gaddr_ld32(void) { void test_gaddr_ld32(void) {
/* Load program, add global data, GADDR + LD32 to read it back */ /* Load program, add global data, GADDR + LD32 to read it back */
spl_ins_t p[] = {ins(SPL_GADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_U32, 0), spl_vm_ins_t p[] = {ins(SPL_GADDR, SPL_VOID, 0), ins(SPL_LOAD, SPL_U32, 0),
ins(SPL_RET, SPL_U32, 0)}; ins(SPL_RET, SPL_U32, 0)};
size_t len; size_t len;
unsigned char *bin = build_binary("main", 0, p, 3, &len); unsigned char *bin = build_binary("main", 0, p, 3, &len);
@@ -697,7 +698,7 @@ void test_gaddr_ld32(void) {
void test_gaddr_multi(void) { void test_gaddr_multi(void) {
/* Two global data entries: read second one via GADDR 1 */ /* Two global data entries: read second one via GADDR 1 */
spl_ins_t p[] = {ins(SPL_GADDR, SPL_VOID, 1), ins(SPL_LOAD, SPL_U32, 0), spl_vm_ins_t p[] = {ins(SPL_GADDR, SPL_VOID, 1), ins(SPL_LOAD, SPL_U32, 0),
ins(SPL_RET, SPL_U32, 0)}; ins(SPL_RET, SPL_U32, 0)};
size_t len; size_t len;
unsigned char *bin = build_binary("main", 0, p, 3, &len); unsigned char *bin = build_binary("main", 0, p, 3, &len);
@@ -731,10 +732,10 @@ void test_gaddr_multi(void) {
void test_ncall(void) { void test_ncall(void) {
/* main() -> i32 { return native_add(30, 12); } */ /* main() -> i32 { return native_add(30, 12); } */
/* NCALL imm = nargs, native index is pushed separately */ /* NCALL imm = nargs, native index is pushed separately */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 30), ins(SPL_PUSH, SPL_I32, 12), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 30), ins(SPL_PUSH, SPL_I32, 12),
ins(SPL_PUSH, SPL_VOID, 0), ins(SPL_NCALL, SPL_I32, 2), ins(SPL_PUSH, SPL_VOID, 0), ins(SPL_NCALL, SPL_I32, 2),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_RET, SPL_I32, 0)};
spl_native_t nat[] = {{"native_add", 0, native_add_impl}}; spl_vm_native_t nat[] = {{"native_add", 0, native_add_impl}};
TEST_CHECK(run_with_natives(p, 5, nat, 1) == 42); TEST_CHECK(run_with_natives(p, 5, nat, 1) == 42);
} }
@@ -744,21 +745,21 @@ void test_ncall(void) {
void test_trunc(void) { void test_trunc(void) {
/* push 0xABCD, trunc to 8 bits -> 0xCD */ /* push 0xABCD, trunc to 8 bits -> 0xCD */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xABCD), ins(SPL_TRUNC, SPL_U8, 8), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xABCD), ins(SPL_TRUNC, SPL_U8, 8),
ins(SPL_RET, SPL_U8, 0)}; ins(SPL_RET, SPL_U8, 0)};
TEST_CHECK(run(p, 3) == 0xCD); TEST_CHECK(run(p, 3) == 0xCD);
} }
void test_sext(void) { void test_sext(void) {
/* push 0x80, sext from 8 bits -> 0xFFFFFF80 */ /* push 0x80, sext from 8 bits -> 0xFFFFFF80 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0x80), ins(SPL_SEXT, SPL_I32, 8), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 0x80), ins(SPL_SEXT, SPL_I32, 8),
ins(SPL_RET, SPL_I32, 0)}; ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 3) == (int)(int8_t)(0x80)); TEST_CHECK(run(p, 3) == (int)(int8_t)(0x80));
} }
void test_zext(void) { void test_zext(void) {
/* push 0xFFFF, zext from 8 bits -> 0xFF */ /* push 0xFFFF, zext from 8 bits -> 0xFF */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF), ins(SPL_ZEXT, SPL_U32, 8), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 0xFFFF), ins(SPL_ZEXT, SPL_U32, 8),
ins(SPL_RET, SPL_U32, 0)}; ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 3) == 0xFF); TEST_CHECK(run(p, 3) == 0xFF);
} }
@@ -769,14 +770,14 @@ void test_zext(void) {
void test_div_u(void) { void test_div_u(void) {
/* unsigned: 100 / 3 = 33 */ /* unsigned: 100 / 3 = 33 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 100), ins(SPL_PUSH, SPL_U32, 3), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 100), ins(SPL_PUSH, SPL_U32, 3),
ins(SPL_DIV_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_DIV_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 33); TEST_CHECK(run(p, 4) == 33);
} }
void test_rem_u(void) { void test_rem_u(void) {
/* unsigned: 100 % 3 = 1 */ /* unsigned: 100 % 3 = 1 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 100), ins(SPL_PUSH, SPL_U32, 3), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_U32, 100), ins(SPL_PUSH, SPL_U32, 3),
ins(SPL_REM_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)}; ins(SPL_REM_U, SPL_U32, 0), ins(SPL_RET, SPL_U32, 0)};
TEST_CHECK(run(p, 4) == 1); TEST_CHECK(run(p, 4) == 1);
} }
@@ -787,15 +788,16 @@ void test_rem_u(void) {
void test_many_ops(void) { void test_many_ops(void) {
/* (1+2) * (3+4) = 21 */ /* (1+2) * (3+4) = 21 */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2), ins(SPL_ADD, SPL_I32, 0), spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 1), ins(SPL_PUSH, SPL_I32, 2),
ins(SPL_PUSH, SPL_I32, 3), ins(SPL_PUSH, SPL_I32, 4), ins(SPL_ADD, SPL_I32, 0), ins(SPL_ADD, SPL_I32, 0), ins(SPL_PUSH, SPL_I32, 3),
ins(SPL_PUSH, SPL_I32, 4), ins(SPL_ADD, SPL_I32, 0),
ins(SPL_MUL, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)}; ins(SPL_MUL, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
TEST_CHECK(run(p, 8) == 21); TEST_CHECK(run(p, 8) == 21);
} }
void test_halt(void) { void test_halt(void) {
/* push 77, halt -> exit code 0 (HALT doesn't pop) */ /* push 77, halt -> exit code 0 (HALT doesn't pop) */
spl_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 77), ins(SPL_HALT, SPL_VOID, 0)}; spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 77), ins(SPL_HALT, SPL_VOID, 0)};
TEST_CHECK(run(p, 2) == 0); TEST_CHECK(run(p, 2) == 0);
} }