stage1 指针计算类型的错误修复 as运算符优先级的修改 ir2vm的bug修复

This commit is contained in:
zzy committed 2026-09-15 21:24:58 +08:00
1 parent 06f3884c30
commit 09d05e3a34
10 files changed
+191 -60

No files matched your search

+6 -2
View File
@@ -637,10 +637,14 @@ int main(int argc, const char **argv) {
spl_vm_t vm;
spl_vm_init(&vm);
if (o.debug)
if (o.debug) {
fprintf(stderr, "spl_cli: debug mode on\n");
spl_vm_set_debug(&vm, 1);
if (o.trace)
}
if (o.trace) {
fprintf(stderr, "spl_cli: trace mode on\n");
spl_vm_set_trace(&vm, 1);
}
if (spl_vm_load_prog(&vm, &prog) != 0) {
fprintf(stderr, "spl_cli: failed to load prog\n");
spl_vm_drop(&vm);
+3 -1
View File
@@ -170,7 +170,9 @@ typedef struct spl_vm_func {
typedef VEC(spl_vm_func_t) spl_vm_func_vec_t;
/* Native function pointer type */
typedef spl_vm_val_t (*spl_vm_fn_t)(int nargs, spl_vm_val_t *args);
struct spl_vm;
typedef struct spl_vm spl_vm_t;
typedef spl_vm_val_t (*spl_vm_fn_t)(spl_vm_t *vm, int nargs, spl_vm_val_t *args);
typedef struct spl_vm_native {
char *name;
spl_vm_val_t idx_of_strtab;
+106 -31
View File
@@ -36,21 +36,21 @@
} while (0)
#define SYSCALL_0(name, ret_expr) \
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 0); \
(void)args; \
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
}
#define SYSCALL_1(name, t1, ret_expr) \
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
static spl_vm_val_t name(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) { \
CHECK_NARGS(#name, 1); \
t1 a1 = (t1)(uintptr_t)args[0]; \
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
}
#define SYSCALL_2(name, t1, t2, ret_expr) \
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
static spl_vm_val_t name(spl_vm_t *_vm, 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]; \
@@ -58,7 +58,7 @@
}
#define SYSCALL_3(name, t1, t2, t3, ret_expr) \
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
static spl_vm_val_t name(spl_vm_t *_vm, 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]; \
@@ -67,7 +67,7 @@
}
#define SYSCALL_4(name, t1, t2, t3, t4, ret_expr) \
static spl_vm_val_t name(int nargs, spl_vm_val_t *args) { \
static spl_vm_val_t name(spl_vm_t *_vm, 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]; \
@@ -76,6 +76,42 @@
return (spl_vm_val_t)(uintptr_t)(ret_expr); \
}
/* syscall / VM 内部统一地址检查宏。
* 失败时打印 ctx + 地址 + size + ip,置 native_error,return 0。
* 要求所在函数有可用的 _vm 变量。 */
#define ADDRCHECK(vm, ptr, size, ctx) \
do { \
uintptr_t _acp = (uintptr_t)(ptr); \
usize _acs = (usize)(size); \
if (!spl_vm_addr_valid(_acp, _acs)) { \
fprintf(stderr, "%s: invalid address %p size=%zu (ip=%zu fp=%zu sp=%zu)\n", (ctx), \
(void *)_acp, _acs, (vm)->ip, (vm)->fp, (vm)->sp); \
spl_vm_backtrace((vm), (vm)->fp); \
(vm)->exit_code = 2; \
return 0; \
} \
} while (0)
/* syscall 内部:把当前栈和调用栈打印出来,供出错时定位 */
#define SYSCALL_DUMP(vm) \
do { \
fprintf(stderr, " --- syscall dump (sp=%zu fp=%zu cp=%zu ip=%zu) ---\n", (vm)->sp, \
(vm)->fp, (vm)->cp, (vm)->ip); \
spl_vm_backtrace((vm), (vm)->fp); \
spl_vm_stackdump((vm), (vm)->sp); \
} while (0)
/* syscall 内部:报告致命错误,dump 后让 VM 停在当前 ip */
#define SYSCALL_FAIL(vm, ...) \
do { \
fprintf(stderr, "syscall error: "); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
SYSCALL_DUMP(vm); \
(vm)->exit_code = 1; \
return 0; \
} while (0)
/* =================================================================
* OS syscalls
* ================================================================= */
@@ -108,7 +144,7 @@ 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_vm_val_t vm_fsize(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_fsize(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_fsize", 1);
FILE *f = (FILE *)(uintptr_t)args[0];
long cur = ftell(f);
@@ -123,7 +159,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_vm_val_t vm_read_file(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_read_file(spl_vm_t *_vm, 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) {
@@ -149,28 +185,69 @@ static spl_vm_val_t vm_read_file(int nargs, spl_vm_val_t *args) {
return (spl_vm_val_t)(uintptr_t)buf;
}
/* vm_alloc - allocate memory (malloc) */
SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1))
static spl_vm_val_t vm_alloc(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_alloc", 1);
size_t sz = (size_t)args[0];
if (sz == 0)
SYSCALL_FAIL(_vm, "vm_alloc: zero size");
if (sz > (size_t)1 << 32)
SYSCALL_FAIL(_vm, "vm_alloc: size too large (%zu)", sz);
void *p = malloc(sz);
if (!p)
SYSCALL_FAIL(_vm, "vm_alloc: malloc(%zu) failed", sz);
return (spl_vm_val_t)(uintptr_t)p;
}
/* vm_free - free memory */
SYSCALL_1(vm_free, void *, (free(a1), (spl_vm_val_t)0))
static spl_vm_val_t vm_free(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_free", 1);
void *p = (void *)(uintptr_t)args[0];
if (p)
free(p);
return 0;
}
/* vm_realloc - reallocate memory (realloc) */
SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2))
static spl_vm_val_t vm_realloc(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_realloc", 2);
void *p = (void *)(uintptr_t)args[0];
size_t sz = (size_t)args[1];
if (!p)
SYSCALL_FAIL(_vm, "vm_realloc: NULL ptr");
if (sz == 0)
SYSCALL_FAIL(_vm, "vm_realloc: zero size");
ADDRCHECK(_vm, p, 1, "vm_realloc");
void *np = realloc(p, sz);
if (!np)
SYSCALL_FAIL(_vm, "vm_realloc: realloc(%p, %zu) failed", p, sz);
return (spl_vm_val_t)(uintptr_t)np;
}
/* vm_strlen - get string length */
SYSCALL_1(vm_strlen, const char *, strlen(a1))
static spl_vm_val_t vm_memcpy(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_memcpy", 3);
void *dst = (void *)(uintptr_t)args[0];
const void *src = (const void *)(uintptr_t)args[1];
size_t size = (size_t)args[2];
if (size == 0)
return (spl_vm_val_t)(uintptr_t)dst;
ADDRCHECK(_vm, dst, size, "vm_memcpy(dst)");
ADDRCHECK(_vm, src, size, "vm_memcpy(src)");
memcpy(dst, src, size);
return (spl_vm_val_t)(uintptr_t)dst;
}
/* vm_strcmp - compare two strings */
SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2))
static spl_vm_val_t vm_memcmp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_memcmp", 3);
const void *a = (const void *)(uintptr_t)args[0];
const void *b = (const void *)(uintptr_t)args[1];
size_t size = (size_t)args[2];
if (size == 0)
return 0;
ADDRCHECK(_vm, a, size, "vm_memcmp(a)");
ADDRCHECK(_vm, b, size, "vm_memcmp(b)");
return (spl_vm_val_t)memcmp(a, b, size);
}
/* vm_memcpy - copy memory, returns dst */
SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1))
/* vm_memcmp - compare two memory */
SYSCALL_3(vm_memcmp, void *, const void *, size_t, (memcmp(a1, a2, a3), (uintptr_t)a1))
static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_printf(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
if (nargs <= 0)
return 0;
@@ -245,7 +322,7 @@ static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
* ================================================================= */
/* vm_new - create a new sub-VM instance, returns spl_vm_t* */
static spl_vm_val_t vm_new(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_new(spl_vm_t *_vm, 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));
@@ -256,7 +333,7 @@ static spl_vm_val_t vm_new(int nargs, spl_vm_val_t *args) {
}
/* vm_drop - destroy a sub-VM and its loaded program */
static spl_vm_val_t vm_drop(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_drop(spl_vm_t *_vm, 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)
@@ -272,7 +349,7 @@ static spl_vm_val_t vm_drop(int nargs, spl_vm_val_t *args) {
}
/* vm_load - load a .sir file, register syscalls, return spl_prog_t* */
static spl_vm_val_t vm_load(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_load(spl_vm_t *_vm, 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];
@@ -296,7 +373,7 @@ static spl_vm_val_t vm_load(int nargs, spl_vm_val_t *args) {
}
/* vm_push - push a value onto the sub-VM's stack (for passing arguments) */
static spl_vm_val_t vm_push(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_push", 2);
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
spl_vm_val_t val = args[1];
@@ -321,7 +398,7 @@ static spl_vm_val_t vm_push(int nargs, spl_vm_val_t *args) {
* - Sets fp = sp - nargs (so arg0 = data[fp], arg1 = data[fp+1], ...)
* - Sets ip to the function address
*/
static spl_vm_val_t vm_call(int nargs, spl_vm_val_t *args) {
static spl_vm_val_t vm_call(spl_vm_t *_vm, 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];
@@ -387,8 +464,6 @@ void spl_syscall_register(spl_prog_t *prog) {
{"vm_alloc", 0, vm_alloc},
{"vm_free", 0, vm_free},
{"vm_realloc", 0, vm_realloc},
{"vm_strlen", 0, vm_strlen},
{"vm_strcmp", 0, vm_strcmp},
{"vm_memcpy", 0, vm_memcpy},
{"vm_memcmp", 0, vm_memcmp},
{"vm_printf", 0, vm_printf},
+30 -4
View File
@@ -587,6 +587,25 @@ void spl_vm_drop(spl_vm_t *vm) {
vec_free(vm->breakpoints);
}
// FIXME
int spl_vm_addr_valid(uintptr_t p, usize size) {
if (p == 0)
return 0;
if (p < 0x1000)
return 0;
uintptr_t max =
(sizeof(void *) == 8) ? (uintptr_t)0x00007FFFFFFFFFFFULL : (uintptr_t)0x7FFFFFFF;
if (p > max)
return 0;
if (size > 0) {
if (p + size < p)
return 0;
if (p + size > max)
return 0;
}
return 1;
}
void spl_vm_add_breakpoint(spl_vm_t *vm, usize ip) {
if (!vm)
return;
@@ -1108,10 +1127,17 @@ int spl_vm_run_once(spl_vm_t *vm) {
VM_ERROR(vm->error_msg);
}
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_vm_val_t _result = _nat->impl_fn(_nargs, _arg_base);
spl_vm_val_t _result = _nat->impl_fn(vm, _nargs, _arg_base);
if (vm->exit_code) {
snprintf(vm->error_msg, sizeof(vm->error_msg), "NCALL %s failed (ip=%zd)",
_nat->name ? _nat->name : "?", vm->ip - 1);
fprintf(stderr, "native call: %s\n", _nat->name ? _nat->name : "?");
fprintf(stderr, " nargs=%zd arg_base=%p sp=%zu\n", _nargs, (void *)_arg_base,
vm->sp);
spl_vm_backtrace(vm, vm->fp);
spl_vm_stackdump(vm, vm->sp);
return -1;
}
vm->sp -= _nargs;
PUSH(_result);
break;
+3 -1
View File
@@ -19,7 +19,7 @@ typedef struct {
typedef VEC(spl_vm_val_t) spl_stack_vec_t;
typedef VEC(spl_callframe_t) spl_frame_vec_t;
typedef struct {
typedef struct spl_vm {
spl_stack_vec_t stacks;
spl_frame_vec_t frames;
uintptr_t gp; // global pointer
@@ -52,6 +52,8 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth);
/* Free dynamically allocated memory in VM */
void spl_vm_drop(spl_vm_t *vm);
int spl_vm_addr_valid(uintptr_t p, usize size);
int spl_vm_load_prog(spl_vm_t *vm, spl_prog_t *prog);
int spl_vm_prepare(spl_vm_t *vm, const char *entry, int argc, const char **argv, const char **envp);