stage0 重命名字段 修复windows函数没有进入宏包装
This commit is contained in:
@@ -189,7 +189,7 @@ typedef struct {
|
||||
|
||||
static const char *fn_name_at(spl_prog_t *prog, usize ip) {
|
||||
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)
|
||||
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;
|
||||
*end = vec_size(prog->insns);
|
||||
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) {
|
||||
*start = f->address;
|
||||
*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) {
|
||||
snprintf(buf, n, "%-11s %-5s %zu", spl_opcode_name(ins->opcode), spl_type_tag_name(ins->type),
|
||||
ins->imm);
|
||||
static void fmt_insn(const spl_vm_ins_t *ins, char *buf, size_t n) {
|
||||
snprintf(buf, n, "%-11s %-5s %zu", spl_vm_opcode_name(ins->opcode),
|
||||
spl_vm_type_kind_name(ins->type), ins->imm);
|
||||
}
|
||||
|
||||
static void dbg_show_location(dbg_t *d) {
|
||||
@@ -539,7 +539,7 @@ static int cmd_x(dbg_t *d, const char *args) {
|
||||
return 0;
|
||||
}
|
||||
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,
|
||||
addr >= (uintptr_t)sbase && addr < (uintptr_t)(sbase + slen));
|
||||
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);
|
||||
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);
|
||||
d->last_ptr = (usize)*addr; /* 供 x 无参重读 */
|
||||
return 0;
|
||||
|
||||
@@ -25,7 +25,7 @@ int main(int argc, const char **argv) {
|
||||
if (vec_size(prog.funcs) > 0) {
|
||||
printf(";; --- functions ---\n");
|
||||
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,
|
||||
f->ninsns, f->address);
|
||||
}
|
||||
@@ -35,7 +35,7 @@ int main(int argc, const char **argv) {
|
||||
if (vec_size(prog.natives) > 0) {
|
||||
printf(";; --- natives ---\n");
|
||||
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("\n");
|
||||
@@ -51,10 +51,10 @@ int main(int argc, const char **argv) {
|
||||
|
||||
printf(";; --- instructions ---\n");
|
||||
for (usize i = 0; i < vec_size(prog.insns); i++) {
|
||||
spl_ins_t *ins = &vec_at(prog.insns, i);
|
||||
printf("%4zd: %s", i, spl_opcode_name((spl_opcode_t)ins->opcode));
|
||||
spl_vm_ins_t *ins = &vec_at(prog.insns, i);
|
||||
printf("%4zd: %s", i, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode));
|
||||
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);
|
||||
|
||||
/* annotate jumps / calls */
|
||||
|
||||
@@ -45,16 +45,16 @@ void spl_prog_drop(spl_prog_t *prog) {
|
||||
|
||||
/* ---- LE read/write helpers ---- */
|
||||
|
||||
static inline spl_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_val_t)(*p)[3] << 24) | ((spl_val_t)(*p)[4] << 32) |
|
||||
((spl_val_t)(*p)[5] << 40) | ((spl_val_t)(*p)[6] << 48) |
|
||||
((spl_val_t)(*p)[7] << 56);
|
||||
static inline spl_vm_val_t rd64(const unsigned char **p) {
|
||||
spl_vm_val_t v = (spl_vm_val_t)(*p)[0] | ((spl_vm_val_t)(*p)[1] << 8) |
|
||||
((spl_vm_val_t)(*p)[2] << 16) | ((spl_vm_val_t)(*p)[3] << 24) |
|
||||
((spl_vm_val_t)(*p)[4] << 32) | ((spl_vm_val_t)(*p)[5] << 40) |
|
||||
((spl_vm_val_t)(*p)[6] << 48) | ((spl_vm_val_t)(*p)[7] << 56);
|
||||
*p += 8;
|
||||
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 >> 8);
|
||||
*(*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;
|
||||
long len;
|
||||
const unsigned char *p;
|
||||
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
||||
spl_vm_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
||||
|
||||
if (!fname || !prog)
|
||||
return -1;
|
||||
@@ -120,9 +120,9 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
|
||||
ndata = rd64(&p);
|
||||
|
||||
/* ---- function table ---- */
|
||||
for (spl_val_t i = 0; i < nfuncs; i++) {
|
||||
spl_func_t func = {0};
|
||||
spl_val_t nlen = rd64(&p);
|
||||
for (spl_vm_val_t i = 0; i < nfuncs; i++) {
|
||||
spl_vm_func_t func = {0};
|
||||
spl_vm_val_t nlen = rd64(&p);
|
||||
usize pad = ALIGN8((usize)nlen) - (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 ---- */
|
||||
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) {
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
spl_ins_t ins;
|
||||
spl_vm_ins_t ins;
|
||||
ins.opcode = (uint16_t)p[0] | ((uint16_t)p[1] << 8);
|
||||
ins.type = (uint16_t)p[2] | ((uint16_t)p[3] << 8);
|
||||
p += 4;
|
||||
@@ -155,9 +155,9 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
|
||||
}
|
||||
|
||||
/* ---- native table ---- */
|
||||
for (spl_val_t i = 0; i < nnatives; i++) {
|
||||
spl_native_t nat = {0};
|
||||
spl_val_t nlen = rd64(&p);
|
||||
for (spl_vm_val_t i = 0; i < nnatives; i++) {
|
||||
spl_vm_native_t nat = {0};
|
||||
spl_vm_val_t nlen = rd64(&p);
|
||||
usize pad = ALIGN8((usize)nlen) - (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 ---- */
|
||||
for (spl_val_t i = 0; i < nstrs; i++) {
|
||||
spl_val_t slen = rd64(&p);
|
||||
for (spl_vm_val_t i = 0; i < nstrs; i++) {
|
||||
spl_vm_val_t slen = rd64(&p);
|
||||
usize pad = ALIGN8((usize)slen) - (usize)slen;
|
||||
char *s = (char *)malloc((usize)slen + 1);
|
||||
if (!s) {
|
||||
@@ -189,8 +189,8 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
|
||||
}
|
||||
|
||||
/* ---- global data ---- */
|
||||
for (spl_val_t i = 0; i < ndata; i++) {
|
||||
spl_gdata_t entry;
|
||||
for (spl_vm_val_t i = 0; i < ndata; i++) {
|
||||
spl_vm_gdata_t entry;
|
||||
entry.size = rd64(&p);
|
||||
usize pad = ALIGN8(entry.size) - 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) {
|
||||
unsigned char *buf, *p;
|
||||
spl_val_t i;
|
||||
spl_vm_val_t i;
|
||||
size_t total;
|
||||
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
||||
spl_vm_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
||||
usize nlen, pad;
|
||||
|
||||
if (!fname || !prog)
|
||||
@@ -306,7 +306,7 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
|
||||
|
||||
/* ---- instructions ---- */
|
||||
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 >> 8);
|
||||
*p++ = (unsigned char)(ins->type);
|
||||
@@ -341,7 +341,7 @@ int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
|
||||
|
||||
/* ---- global data ---- */
|
||||
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;
|
||||
wr64(&p, 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;
|
||||
}
|
||||
|
||||
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)
|
||||
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);
|
||||
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)
|
||||
return 0;
|
||||
vec_push(prog->funcs, *func);
|
||||
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)
|
||||
return 0;
|
||||
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) {
|
||||
spl_gdata_t entry;
|
||||
spl_vm_gdata_t entry;
|
||||
if (!prog)
|
||||
return 0;
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
return NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
return NULL;
|
||||
vec_for(prog->natives, i) {
|
||||
@@ -426,8 +426,8 @@ const char *opcode_name[] = {
|
||||
SPL_OPCODES(X)
|
||||
#undef X
|
||||
};
|
||||
const char *spl_opcode_name(spl_opcode_t opcode) { return opcode_name[opcode]; }
|
||||
const char *spl_type_tag_name(spl_type_t type) {
|
||||
const char *spl_vm_opcode_name(spl_vm_opcode_t opcode) { return opcode_name[opcode]; }
|
||||
const char *spl_vm_type_kind_name(spl_type_t type) {
|
||||
switch (type) {
|
||||
case SPL_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) {
|
||||
printf("%4zu: %s", addr, spl_opcode_name((spl_opcode_t)ins->opcode));
|
||||
void spl_vm_ins_dump(spl_vm_ins_t *ins, spl_vm_val_t addr) {
|
||||
printf("%4zu: %s", addr, spl_vm_opcode_name((spl_vm_opcode_t)ins->opcode));
|
||||
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("\n");
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ typedef enum {
|
||||
#define X(opcode, name, argc, pop, push, desc) opcode,
|
||||
SPL_OPCODES(X)
|
||||
#undef X
|
||||
} spl_opcode_t;
|
||||
} spl_vm_opcode_t;
|
||||
|
||||
/*
|
||||
* Binary format (all metadata fields spl_val_t LE):
|
||||
@@ -151,48 +151,48 @@ typedef enum {
|
||||
|
||||
#define SPL_BINFMT_MAGIC "SPLBIN\0\0"
|
||||
// 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 type;
|
||||
spl_val_t imm;
|
||||
} spl_ins_t;
|
||||
typedef VEC(spl_ins_t) spl_ins_vec_t;
|
||||
spl_vm_val_t imm;
|
||||
} spl_vm_ins_t;
|
||||
typedef VEC(spl_vm_ins_t) spl_vm_ins_vec_t;
|
||||
|
||||
typedef struct spl_func {
|
||||
typedef struct spl_vm_func {
|
||||
char *name;
|
||||
spl_val_t idx_of_strtab;
|
||||
spl_val_t nargs;
|
||||
spl_val_t ninsns;
|
||||
spl_val_t address;
|
||||
} spl_func_t;
|
||||
typedef VEC(spl_func_t) spl_func_vec_t;
|
||||
spl_vm_val_t idx_of_strtab;
|
||||
spl_vm_val_t nargs;
|
||||
spl_vm_val_t ninsns;
|
||||
spl_vm_val_t address;
|
||||
} spl_vm_func_t;
|
||||
typedef VEC(spl_vm_func_t) spl_vm_func_vec_t;
|
||||
|
||||
/* Native function pointer type */
|
||||
typedef spl_val_t (*spl_fn_t)(int nargs, spl_val_t *args);
|
||||
typedef struct spl_native {
|
||||
typedef spl_vm_val_t (*spl_vm_fn_t)(int nargs, spl_vm_val_t *args);
|
||||
typedef struct spl_vm_native {
|
||||
char *name;
|
||||
spl_val_t idx_of_strtab;
|
||||
spl_fn_t impl_fn;
|
||||
} spl_native_t;
|
||||
typedef VEC(spl_native_t) spl_native_vec_t;
|
||||
spl_vm_val_t idx_of_strtab;
|
||||
spl_vm_fn_t impl_fn;
|
||||
} spl_vm_native_t;
|
||||
typedef VEC(spl_vm_native_t) spl_vm_native_vec_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
usize size;
|
||||
} spl_gdata_t;
|
||||
typedef VEC(spl_gdata_t) spl_data_t;
|
||||
typedef VEC(const char *) spl_strtab_t;
|
||||
typedef MAP(const char *, const char *) spl_symtab_t;
|
||||
} spl_vm_gdata_t;
|
||||
typedef VEC(spl_vm_gdata_t) spl_vm_data_t;
|
||||
typedef VEC(const char *) spl_vm_strtab_t;
|
||||
typedef MAP(const char *, const char *) spl_vm_symtab_t;
|
||||
/* Opaque handle for loaded program */
|
||||
typedef struct spl_prog {
|
||||
spl_ins_vec_t insns;
|
||||
spl_func_vec_t funcs;
|
||||
spl_native_vec_t natives;
|
||||
spl_data_t gdata;
|
||||
spl_strtab_t strtab;
|
||||
spl_symtab_t symtab;
|
||||
spl_vm_ins_vec_t insns;
|
||||
spl_vm_func_vec_t funcs;
|
||||
spl_vm_native_vec_t natives;
|
||||
spl_vm_data_t gdata;
|
||||
spl_vm_strtab_t strtab;
|
||||
spl_vm_symtab_t symtab;
|
||||
char *debug; /* 文件尾部 debug 段(splc0 -g 追加的文本),无则 NULL */
|
||||
usize debug_size;
|
||||
} 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_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_func(spl_prog_t *prog, spl_func_t *func);
|
||||
int spl_prog_add_native(spl_prog_t *prog, spl_native_t *native);
|
||||
int spl_prog_add_func(spl_prog_t *prog, spl_vm_func_t *func);
|
||||
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_native_t *spl_prog_get_native(spl_prog_t *prog, const char *name);
|
||||
spl_vm_func_t *spl_prog_get_func(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 */
|
||||
const char *spl_opcode_name(spl_opcode_t opcode);
|
||||
const char *spl_type_tag_name(spl_type_t type);
|
||||
const char *spl_vm_opcode_name(spl_vm_opcode_t opcode);
|
||||
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__ */
|
||||
|
||||
@@ -36,44 +36,44 @@
|
||||
} while (0)
|
||||
|
||||
#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); \
|
||||
(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) \
|
||||
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); \
|
||||
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) \
|
||||
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); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
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) \
|
||||
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); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||
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) \
|
||||
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); \
|
||||
t1 a1 = (t1)(uintptr_t)args[0]; \
|
||||
t2 a2 = (t2)(uintptr_t)args[1]; \
|
||||
t3 a3 = (t3)(uintptr_t)args[2]; \
|
||||
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 */
|
||||
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 */
|
||||
SYSCALL_1(vm_putchar, int, putchar(a1))
|
||||
@@ -90,10 +90,10 @@ SYSCALL_1(vm_putchar, int, putchar(a1))
|
||||
SYSCALL_0(vm_getchar, getchar())
|
||||
|
||||
/* 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) */
|
||||
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 */
|
||||
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))
|
||||
|
||||
/* 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);
|
||||
FILE *f = (FILE *)(uintptr_t)args[0];
|
||||
long cur = ftell(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
long sz = ftell(f);
|
||||
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)
|
||||
@@ -123,7 +123,7 @@ SYSCALL_0(vm_stdout, stdout)
|
||||
SYSCALL_0(vm_stderr, stderr)
|
||||
|
||||
/* 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);
|
||||
const char *path = (const char *)(uintptr_t)args[0];
|
||||
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);
|
||||
fclose(f);
|
||||
buf[nread] = '\0';
|
||||
return (spl_val_t)(uintptr_t)buf;
|
||||
return (spl_vm_val_t)(uintptr_t)buf;
|
||||
}
|
||||
|
||||
/* vm_alloc - allocate memory (malloc) */
|
||||
SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1))
|
||||
|
||||
/* 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) */
|
||||
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 */
|
||||
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;
|
||||
if (nargs <= 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* */
|
||||
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);
|
||||
(void)args;
|
||||
spl_vm_t *vm = (spl_vm_t *)malloc(sizeof(spl_vm_t));
|
||||
if (!vm)
|
||||
return 0;
|
||||
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 */
|
||||
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);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
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* */
|
||||
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);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
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);
|
||||
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) */
|
||||
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);
|
||||
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)
|
||||
return -1;
|
||||
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 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);
|
||||
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
|
||||
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)
|
||||
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) {
|
||||
fprintf(stderr, "vm_call: function '%s' not found\n", name);
|
||||
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) {
|
||||
static spl_native_t table[] = {
|
||||
static spl_vm_native_t table[] = {
|
||||
/* OS operations */
|
||||
{"vm_exit", 0, vm_exit},
|
||||
{"vm_putchar", 0, vm_putchar},
|
||||
@@ -393,7 +393,7 @@ void spl_syscall_register(spl_prog_t *prog) {
|
||||
if (!prog)
|
||||
return;
|
||||
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)
|
||||
continue;
|
||||
for (int j = 0; j < n; j++) {
|
||||
|
||||
172
stage0/spl_vm.c
172
stage0/spl_vm.c
@@ -99,7 +99,7 @@ static int spl_type_size(spl_type_t t) {
|
||||
|
||||
#define PUSH(v) \
|
||||
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) \
|
||||
VM_ERROR("stack overflow"); \
|
||||
vm->stacks.data[(vm->sp)++] = _pv; \
|
||||
@@ -121,8 +121,8 @@ static int spl_type_size(spl_type_t t) {
|
||||
|
||||
#define ARITH_BINOP(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_val_t _r = 0; \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _r = 0; \
|
||||
if (spl_is_float((spl_type_t)ins->type)) { \
|
||||
double _da, _db, _dr; \
|
||||
if (ins->type == SPL_F32) { \
|
||||
@@ -145,25 +145,25 @@ static int spl_type_size(spl_type_t t) {
|
||||
} else { \
|
||||
switch (ins->type) { \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
case SPL_U64: \
|
||||
case SPL_PTR: \
|
||||
@@ -181,10 +181,10 @@ static int spl_type_size(spl_type_t t) {
|
||||
/* signed division / remainder - all types cast to signed */
|
||||
#define DIV_REM_S(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
if (_b == 0) \
|
||||
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)) { \
|
||||
double _da, _db, _dr; \
|
||||
if (ins->type == SPL_F32) { \
|
||||
@@ -207,31 +207,31 @@ static int spl_type_size(spl_type_t t) {
|
||||
} else { \
|
||||
switch (ins->type) { \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
case SPL_U64: \
|
||||
case SPL_PTR: \
|
||||
case SPL_USIZE: \
|
||||
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; \
|
||||
default: \
|
||||
VM_ERROR("bad type for signed division"); \
|
||||
@@ -243,31 +243,31 @@ static int spl_type_size(spl_type_t t) {
|
||||
/* unsigned division / remainder */
|
||||
#define DIV_REM_U(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
if (_b == 0) \
|
||||
VM_ERROR("division by zero"); \
|
||||
spl_val_t _r = 0; \
|
||||
spl_vm_val_t _r = 0; \
|
||||
switch (ins->type) { \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
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; \
|
||||
case SPL_U64: \
|
||||
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) */
|
||||
#define CMP_ALL(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
intptr_t _r = 0; \
|
||||
switch (ins->type) { \
|
||||
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) */
|
||||
#define CMP_S(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
intptr_t _r = 0; \
|
||||
switch (ins->type) { \
|
||||
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) */
|
||||
#define CMP_U(OP) \
|
||||
do { \
|
||||
spl_val_t _b = POP(), _a = POP(); \
|
||||
spl_vm_val_t _b = POP(), _a = POP(); \
|
||||
intptr_t _r = 0; \
|
||||
switch (ins->type) { \
|
||||
case SPL_I8: \
|
||||
@@ -478,6 +478,7 @@ const char *ExceptionCodeToString(DWORD code) {
|
||||
}
|
||||
|
||||
// 全局未处理异常过滤器
|
||||
#ifdef _WIN32
|
||||
LONG WINAPI UnhandledExceptionFilterImpl(EXCEPTION_POINTERS *pExceptionInfo) {
|
||||
// 获取异常记录和上下文
|
||||
PEXCEPTION_RECORD record = pExceptionInfo->ExceptionRecord;
|
||||
@@ -537,6 +538,7 @@ LONG WINAPI UnhandledExceptionFilterImpl(EXCEPTION_POINTERS *pExceptionInfo) {
|
||||
// 你可以在这里调用 exit(1) 或直接返回,进程会被终止
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ================================================================
|
||||
* spl_vm_init / spl_vm_drop
|
||||
@@ -614,10 +616,10 @@ void spl_vm_skip_breakpoint(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
/* 前向声明(定义在文件尾部 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 所在函数名是否在断点表 */
|
||||
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))
|
||||
return 0;
|
||||
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]
|
||||
|
||||
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)
|
||||
VM_ERROR("CALLI: call stack overflow");
|
||||
// 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) {
|
||||
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) {
|
||||
fprintf(stderr, "vm: entry point '%s' not found\n", entry ? entry : "main");
|
||||
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) {
|
||||
const spl_ins_t *ins;
|
||||
const spl_vm_ins_t *ins;
|
||||
spl_prog_t *prog;
|
||||
|
||||
if (!vm || !vm->prog)
|
||||
@@ -761,7 +763,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
if (vm->trace) {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -775,7 +777,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
case SPL_DUP: {
|
||||
if (vm->sp < 1)
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@@ -789,7 +791,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
case SPL_SWAP: {
|
||||
if (vm->sp < 2)
|
||||
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 - 2] = _t;
|
||||
break;
|
||||
@@ -806,9 +808,9 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
case SPL_ROT: {
|
||||
if (vm->sp < 3)
|
||||
VM_ERROR("ROT: stack underflow");
|
||||
spl_val_t _a = vm->stacks.data[vm->sp - 3];
|
||||
spl_val_t _b = vm->stacks.data[vm->sp - 2];
|
||||
spl_val_t _c = vm->stacks.data[vm->sp - 1];
|
||||
spl_vm_val_t _a = vm->stacks.data[vm->sp - 3];
|
||||
spl_vm_val_t _b = vm->stacks.data[vm->sp - 2];
|
||||
spl_vm_val_t _c = vm->stacks.data[vm->sp - 1];
|
||||
vm->stacks.data[vm->sp - 3] = _b;
|
||||
vm->stacks.data[vm->sp - 2] = _c;
|
||||
vm->stacks.data[vm->sp - 1] = _a;
|
||||
@@ -840,7 +842,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
break;
|
||||
|
||||
case SPL_NEG: {
|
||||
spl_val_t _a = POP();
|
||||
spl_vm_val_t _a = POP();
|
||||
if (spl_is_float((spl_type_t)ins->type)) {
|
||||
double _d;
|
||||
if (ins->type == SPL_F32) {
|
||||
@@ -862,17 +864,17 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
/* ========== Bitwise ========== */
|
||||
case SPL_AND: {
|
||||
spl_val_t _b = POP(), _a = POP();
|
||||
spl_vm_val_t _b = POP(), _a = POP();
|
||||
PUSH(_a & _b);
|
||||
break;
|
||||
}
|
||||
case SPL_OR: {
|
||||
spl_val_t _b = POP(), _a = POP();
|
||||
spl_vm_val_t _b = POP(), _a = POP();
|
||||
PUSH(_a | _b);
|
||||
break;
|
||||
}
|
||||
case SPL_XOR: {
|
||||
spl_val_t _b = POP(), _a = POP();
|
||||
spl_vm_val_t _b = POP(), _a = POP();
|
||||
PUSH(_a ^ _b);
|
||||
break;
|
||||
}
|
||||
@@ -946,8 +948,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
case SPL_CALL: {
|
||||
spl_val_t _nargs = ins->imm;
|
||||
spl_val_t _addr = POP();
|
||||
spl_vm_val_t _nargs = ins->imm;
|
||||
spl_vm_val_t _addr = POP();
|
||||
int _hit = fn_breakpoint_hit(vm, _addr);
|
||||
spl_vm_call(vm, _addr, _nargs);
|
||||
if (_hit)
|
||||
@@ -956,8 +958,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
case SPL_CALLI: {
|
||||
spl_val_t _addr = POP();
|
||||
spl_val_t _nargs = POP();
|
||||
spl_vm_val_t _addr = POP();
|
||||
spl_vm_val_t _nargs = POP();
|
||||
int _hit = fn_breakpoint_hit(vm, _addr);
|
||||
spl_vm_call(vm, _addr, _nargs);
|
||||
if (_hit)
|
||||
@@ -966,7 +968,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
case SPL_RET: {
|
||||
spl_val_t _retval = 0;
|
||||
spl_vm_val_t _retval = 0;
|
||||
if (ins->type != SPL_VOID)
|
||||
_retval = POP();
|
||||
if (vm->cp <= 0)
|
||||
@@ -996,7 +998,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
/* ========== Stack / Frame Local Memory ========== */
|
||||
case SPL_ALLOC: {
|
||||
spl_val_t _k = ins->imm;
|
||||
spl_vm_val_t _k = ins->imm;
|
||||
uintptr_t _new_sp = vm->sp + _k;
|
||||
if (_new_sp > vm->config.max_stack_depth)
|
||||
VM_ERROR("ALLOC: stack overflow");
|
||||
@@ -1007,14 +1009,14 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
case SPL_GADDR: {
|
||||
spl_val_t _idx = ins->imm;
|
||||
spl_vm_val_t _idx = ins->imm;
|
||||
if (_idx >= vec_size(prog->gdata))
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1022,19 +1024,19 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
case SPL_LOAD: {
|
||||
void *_addr = (void *)POP();
|
||||
CHECK_ADDR(_addr, "LOAD");
|
||||
spl_val_t _v = 0;
|
||||
spl_vm_val_t _v = 0;
|
||||
usize _sz = spl_type_size(ins->type);
|
||||
memcpy(&_v, _addr, _sz);
|
||||
/* Sign-extend signed integer types smaller than 64 bits */
|
||||
if (_sz > 0 && _sz < sizeof(spl_val_t) && spl_is_signed(ins->type)) {
|
||||
usize _shift = (sizeof(spl_val_t) - _sz) * 8;
|
||||
_v = (spl_val_t)(((isize)(_v << _shift)) >> _shift);
|
||||
if (_sz > 0 && _sz < sizeof(spl_vm_val_t) && spl_is_signed(ins->type)) {
|
||||
usize _shift = (sizeof(spl_vm_val_t) - _sz) * 8;
|
||||
_v = (spl_vm_val_t)(((isize)(_v << _shift)) >> _shift);
|
||||
}
|
||||
PUSH(_v);
|
||||
break;
|
||||
}
|
||||
case SPL_STORE: {
|
||||
spl_val_t _v = POP();
|
||||
spl_vm_val_t _v = POP();
|
||||
void *_addr = (void *)POP();
|
||||
CHECK_ADDR(_addr, "STORE");
|
||||
memcpy(_addr, &_v, spl_type_size(ins->type));
|
||||
@@ -1043,12 +1045,12 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
|
||||
/* ========== Type Conversion ========== */
|
||||
case SPL_TRUNC: {
|
||||
spl_val_t _v = POP();
|
||||
spl_vm_val_t _v = POP();
|
||||
intptr_t _bits = ins->imm;
|
||||
if (_bits < 1 || _bits > 64)
|
||||
VM_ERROR("TRUNC: bad bit-width");
|
||||
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;
|
||||
}
|
||||
PUSH(_v);
|
||||
@@ -1056,13 +1058,13 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
case SPL_SEXT: {
|
||||
spl_val_t _v = POP();
|
||||
spl_vm_val_t _v = POP();
|
||||
intptr_t _bits = ins->imm;
|
||||
if (_bits < 1 || _bits > 64)
|
||||
VM_ERROR("SEXT: bad bit-width");
|
||||
if (_bits < 64) {
|
||||
spl_val_t _sign = (spl_val_t)1 << (_bits - 1);
|
||||
spl_val_t _mask = ((spl_val_t)1 << _bits) - 1;
|
||||
spl_vm_val_t _sign = (spl_vm_val_t)1 << (_bits - 1);
|
||||
spl_vm_val_t _mask = ((spl_vm_val_t)1 << _bits) - 1;
|
||||
_v &= _mask;
|
||||
if (_v & _sign)
|
||||
_v |= ~_mask;
|
||||
@@ -1072,12 +1074,12 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
}
|
||||
|
||||
case SPL_ZEXT: {
|
||||
spl_val_t _v = POP();
|
||||
spl_vm_val_t _v = POP();
|
||||
intptr_t _bits = ins->imm;
|
||||
if (_bits < 1 || _bits > 64)
|
||||
VM_ERROR("ZEXT: bad bit-width");
|
||||
if (_bits < 64)
|
||||
_v &= ((spl_val_t)1 << _bits) - 1;
|
||||
_v &= ((spl_vm_val_t)1 << _bits) - 1;
|
||||
PUSH(_v);
|
||||
break;
|
||||
}
|
||||
@@ -1085,8 +1087,8 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
||||
/* ========== Native Interface ========== */
|
||||
case SPL_NCALL: {
|
||||
intptr_t _nargs = ins->imm;
|
||||
spl_val_t _nat_idx = POP();
|
||||
spl_native_t *_nat;
|
||||
spl_vm_val_t _nat_idx = POP();
|
||||
spl_vm_native_t *_nat;
|
||||
if (_nat_idx >= vec_size(prog->natives))
|
||||
VM_ERROR("NCALL: native index out of range");
|
||||
_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);
|
||||
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);
|
||||
// printf("addr %p nargs %zd sp %zd stack %p arg_base %p\n", _nat->impl_fn, _nargs, vm->sp,
|
||||
// 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;
|
||||
PUSH(_result);
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_NLIB: {
|
||||
spl_val_t _si = ins->imm;
|
||||
spl_vm_val_t _si = ins->imm;
|
||||
const char *_lib;
|
||||
if (_si >= vec_size(prog->strtab) || !vec_at(prog->strtab, _si))
|
||||
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) {
|
||||
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))
|
||||
return f->name;
|
||||
}
|
||||
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)
|
||||
return;
|
||||
if (ip >= vec_size(vm->prog->insns))
|
||||
return;
|
||||
spl_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),
|
||||
spl_type_tag_name(ins->type), ins->imm);
|
||||
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_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)
|
||||
return;
|
||||
fprintf(stderr, "stack dump (sp=%zd, fp=%zd):\n", sp, vm->fp);
|
||||
spl_val_t start = sp > 32 ? sp - 32 : 0;
|
||||
for (spl_val_t i = start; i <= sp; i++) {
|
||||
spl_vm_val_t start = sp > 32 ? sp - 32 : 0;
|
||||
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],
|
||||
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)
|
||||
return -1;
|
||||
(void)fp;
|
||||
fprintf(stderr, "backtrace: \n");
|
||||
for (isize i = vm->cp - 1; i >= 0; i--) {
|
||||
spl_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_ip = vm->frames.data[i].saved_ip;
|
||||
spl_vm_val_t _saved_fp = vm->frames.data[i].saved_fp;
|
||||
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,
|
||||
vm->frames.data[i].nargs);
|
||||
|
||||
@@ -7,16 +7,16 @@
|
||||
#include "spl_mcode.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SPL_STACK_CANARY ((spl_val_t)0xDEADBEEFCAFEBABEull)
|
||||
#define SPL_STACK_CANARY ((spl_vm_val_t)0xDEADBEEFCAFEBABEull)
|
||||
|
||||
typedef struct {
|
||||
uintptr_t saved_sp;
|
||||
uintptr_t saved_fp;
|
||||
uintptr_t saved_ip;
|
||||
spl_val_t nargs;
|
||||
spl_vm_val_t nargs;
|
||||
} 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 struct {
|
||||
@@ -71,8 +71,8 @@ void spl_vm_clear_breakpoints(spl_vm_t *vm);
|
||||
/* 让 run_once 执行当前指令(忽略一次断点命中);continue 越过当前断点用 */
|
||||
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_stackdump(spl_vm_t *vm, spl_val_t sp);
|
||||
int spl_vm_backtrace(spl_vm_t *vm, spl_val_t fp);
|
||||
void spl_vm_dump_instr(spl_vm_t *vm, spl_vm_val_t ip);
|
||||
void spl_vm_stackdump(spl_vm_t *vm, spl_vm_val_t sp);
|
||||
int spl_vm_backtrace(spl_vm_t *vm, spl_vm_val_t fp);
|
||||
|
||||
#endif /* __SPL_VM_H__ */
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define LE64(p, v) \
|
||||
do { \
|
||||
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 >> 8); \
|
||||
*_p++ = (unsigned char)(_v >> 16); \
|
||||
@@ -33,8 +33,8 @@
|
||||
} while (0)
|
||||
|
||||
/* Convenience: build spl_ins_t from raw fields */
|
||||
static spl_ins_t ins(uint16_t op, uint16_t type, spl_val_t imm) {
|
||||
spl_ins_t x;
|
||||
static spl_vm_ins_t ins(uint16_t op, uint16_t type, spl_vm_val_t imm) {
|
||||
spl_vm_ins_t x;
|
||||
x.opcode = op;
|
||||
x.type = type;
|
||||
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.
|
||||
* 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,
|
||||
int ninsns, size_t *out_len) {
|
||||
static unsigned char *build_binary(const char *fname, spl_vm_val_t nargs,
|
||||
const spl_vm_ins_t *instns, int ninsns, size_t *out_len) {
|
||||
size_t nlen = strlen(fname) + 1;
|
||||
size_t npad = ((nlen + 7) / 8) * 8 - nlen;
|
||||
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);
|
||||
p += 8; /* magic */
|
||||
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); /* nstrs */
|
||||
LE64(p, 0); /* ndata */
|
||||
|
||||
/* func entry */
|
||||
LE64(p, (spl_val_t)nlen); /* name_len */
|
||||
LE64(p, (spl_vm_val_t)nlen); /* name_len */
|
||||
memcpy(p, fname, nlen);
|
||||
p += nlen;
|
||||
memset(p, 0, npad);
|
||||
p += npad;
|
||||
LE64(p, 0); /* idx_of_strtab */
|
||||
LE64(p, nargs);
|
||||
LE64(p, (spl_val_t)ninsns);
|
||||
LE64(p, (spl_vm_val_t)ninsns);
|
||||
LE64(p, 0); /* address = 0 */
|
||||
|
||||
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). */
|
||||
static int run(const spl_ins_t *instns, int ninsns) {
|
||||
static int run(const spl_vm_ins_t *instns, int ninsns) {
|
||||
size_t len;
|
||||
unsigned char *bin = build_binary("main", 0, instns, ninsns, &len);
|
||||
spl_prog_t prog;
|
||||
@@ -127,7 +127,7 @@ static int run(const spl_ins_t *instns, int ninsns) {
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
size_t 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
|
||||
* ================================================================ */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -168,24 +168,24 @@ static spl_val_t native_add_impl(int nargs, spl_val_t *args) {
|
||||
* ================================================================ */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 198);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
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_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 5) == 2);
|
||||
@@ -193,7 +193,7 @@ void test_swap(void) {
|
||||
|
||||
void test_pick(void) {
|
||||
/* 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_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 6) == 50);
|
||||
@@ -204,43 +204,43 @@ void test_pick(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),
|
||||
ins(SPL_RET, SPL_I32, 0)};
|
||||
spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 2), ins(SPL_PUSH, SPL_I32, 3),
|
||||
ins(SPL_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 4) == 5);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 7);
|
||||
}
|
||||
|
||||
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),
|
||||
ins(SPL_RET, SPL_I32, 0)};
|
||||
spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, 6), ins(SPL_PUSH, SPL_I32, 7),
|
||||
ins(SPL_MUL, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 4) == 42);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 33);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 3) == -42);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -249,45 +249,46 @@ void test_i64_arith(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)};
|
||||
TEST_CHECK(run(p, 4) == 0x0F00);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 0xFFFF);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 0xF00F);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 3) == (unsigned int)0x0000FFFF);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1024);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
void test_shr_s(void) {
|
||||
/* 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),
|
||||
ins(SPL_SHR_S, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
|
||||
spl_vm_ins_t p[] = {ins(SPL_PUSH, SPL_I32, (spl_vm_val_t)(int32_t)-1024),
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -296,68 +297,68 @@ void test_shr_s(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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
void test_gt_signed(void) {
|
||||
/* -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)};
|
||||
TEST_CHECK(run(p, 4) == 0);
|
||||
}
|
||||
|
||||
void test_sle(void) {
|
||||
/* -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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
void test_sge(void) {
|
||||
/* -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)};
|
||||
TEST_CHECK(run(p, 4) == 0);
|
||||
}
|
||||
|
||||
void test_ult(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 0);
|
||||
}
|
||||
|
||||
void test_ule(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
void test_ugt(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
|
||||
void test_uge(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
@@ -369,7 +370,7 @@ void test_uge(void) {
|
||||
void test_jmp(void) {
|
||||
/* 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 */
|
||||
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_ADD, SPL_I32, 0), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 6) == 4);
|
||||
@@ -377,13 +378,13 @@ void test_jmp(void) {
|
||||
|
||||
void test_bz_bnz(void) {
|
||||
/* 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, 1), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(p, 6) == 1);
|
||||
|
||||
/* 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, 42), ins(SPL_RET, SPL_I32, 0)};
|
||||
TEST_CHECK(run(q, 6) == 42);
|
||||
@@ -395,7 +396,7 @@ void test_bz_bnz(void) {
|
||||
|
||||
void test_alloc_laddr_st64_ld64(void) {
|
||||
/* 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_LADDR, SPL_VOID, 0), /* 1: addr of local[0] */
|
||||
ins(SPL_PUSH, SPL_I64, 42), /* 2: value */
|
||||
@@ -409,7 +410,7 @@ void test_alloc_laddr_st64_ld64(void) {
|
||||
|
||||
void test_alloc_zeroed(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 0);
|
||||
}
|
||||
@@ -420,7 +421,7 @@ void test_alloc_zeroed(void) {
|
||||
|
||||
void test_ld_st64(void) {
|
||||
/* 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_STORE, SPL_I64, 0), ins(SPL_LOAD, SPL_I64, 0),
|
||||
ins(SPL_RET, SPL_I64, 0)};
|
||||
@@ -428,7 +429,7 @@ void test_ld_st64(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_STORE, SPL_U32, 0), ins(SPL_LOAD, SPL_U32, 0),
|
||||
ins(SPL_RET, SPL_U32, 0)};
|
||||
@@ -436,7 +437,7 @@ void test_ld_st32(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_STORE, SPL_U16, 0), ins(SPL_LOAD, SPL_U16, 0),
|
||||
ins(SPL_RET, SPL_U16, 0)};
|
||||
@@ -444,7 +445,7 @@ void test_ld_st16(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_STORE, SPL_U8, 0), ins(SPL_LOAD, SPL_U8, 0),
|
||||
ins(SPL_RET, SPL_U8, 0)};
|
||||
@@ -475,10 +476,10 @@ void test_call_add(void) {
|
||||
* call 2 ip=9 nargs=2
|
||||
* 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_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_RET, SPL_I64, 0)};
|
||||
|
||||
@@ -499,32 +500,32 @@ void test_call_add(void) {
|
||||
memcpy(p, "SPLBIN\0\0", 8);
|
||||
p += 8;
|
||||
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);
|
||||
|
||||
/* func[0]: "add" */
|
||||
LE64(p, (spl_val_t)nlen0);
|
||||
LE64(p, (spl_vm_val_t)nlen0);
|
||||
memcpy(p, "add", nlen0);
|
||||
p += nlen0;
|
||||
memset(p, 0, npad0);
|
||||
p += npad0;
|
||||
LE64(p, 0);
|
||||
LE64(p, 2);
|
||||
LE64(p, (spl_val_t)nadd);
|
||||
LE64(p, (spl_vm_val_t)nadd);
|
||||
LE64(p, 0);
|
||||
|
||||
/* func[1]: "main" */
|
||||
LE64(p, (spl_val_t)nlen1);
|
||||
LE64(p, (spl_vm_val_t)nlen1);
|
||||
memcpy(p, "main", nlen1);
|
||||
p += nlen1;
|
||||
memset(p, 0, npad1);
|
||||
p += npad1;
|
||||
LE64(p, 0);
|
||||
LE64(p, 0);
|
||||
LE64(p, (spl_val_t)nmain);
|
||||
LE64(p, (spl_val_t)nadd); /* address */
|
||||
LE64(p, (spl_vm_val_t)nmain);
|
||||
LE64(p, (spl_vm_val_t)nadd); /* address */
|
||||
|
||||
for (int i = 0; i < nadd; i++) {
|
||||
*p++ = (unsigned char)(add_insns[i].opcode);
|
||||
@@ -582,10 +583,10 @@ void test_calli(void) {
|
||||
* calli ip=10
|
||||
* 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_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_CALLI, SPL_VOID, 0), ins(SPL_RET, SPL_I64, 0)};
|
||||
|
||||
@@ -602,13 +603,13 @@ void test_calli(void) {
|
||||
memcpy(p, "SPLBIN\0\0", 8);
|
||||
p += 8;
|
||||
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);
|
||||
|
||||
/* func[0]: add */
|
||||
LE64(p, (spl_val_t)nlen0);
|
||||
LE64(p, (spl_vm_val_t)nlen0);
|
||||
memcpy(p, "add", nlen0);
|
||||
p += nlen0;
|
||||
memset(p, 0, npad0);
|
||||
@@ -619,7 +620,7 @@ void test_calli(void) {
|
||||
LE64(p, 0);
|
||||
|
||||
/* func[1]: main */
|
||||
LE64(p, (spl_val_t)nlen1);
|
||||
LE64(p, (spl_vm_val_t)nlen1);
|
||||
memcpy(p, "main", nlen1);
|
||||
p += nlen1;
|
||||
memset(p, 0, npad1);
|
||||
@@ -669,7 +670,7 @@ void test_calli(void) {
|
||||
|
||||
void test_gaddr_ld32(void) {
|
||||
/* 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)};
|
||||
size_t 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) {
|
||||
/* 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)};
|
||||
size_t len;
|
||||
unsigned char *bin = build_binary("main", 0, p, 3, &len);
|
||||
@@ -731,10 +732,10 @@ void test_gaddr_multi(void) {
|
||||
void test_ncall(void) {
|
||||
/* main() -> i32 { return native_add(30, 12); } */
|
||||
/* 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_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);
|
||||
}
|
||||
|
||||
@@ -744,21 +745,21 @@ void test_ncall(void) {
|
||||
|
||||
void test_trunc(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 3) == 0xCD);
|
||||
}
|
||||
|
||||
void test_sext(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 3) == (int)(int8_t)(0x80));
|
||||
}
|
||||
|
||||
void test_zext(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 3) == 0xFF);
|
||||
}
|
||||
@@ -769,14 +770,14 @@ void test_zext(void) {
|
||||
|
||||
void test_div_u(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 33);
|
||||
}
|
||||
|
||||
void test_rem_u(void) {
|
||||
/* 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)};
|
||||
TEST_CHECK(run(p, 4) == 1);
|
||||
}
|
||||
@@ -787,15 +788,16 @@ void test_rem_u(void) {
|
||||
|
||||
void test_many_ops(void) {
|
||||
/* (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),
|
||||
ins(SPL_PUSH, SPL_I32, 3), ins(SPL_PUSH, SPL_I32, 4), 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_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)};
|
||||
TEST_CHECK(run(p, 8) == 21);
|
||||
}
|
||||
|
||||
void test_halt(void) {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user