stage1 部分功能测试00,01,02,06成功

This commit is contained in:
zzy
2026-07-05 18:23:33 +08:00
parent 50b07074fb
commit 51d8510b79
30 changed files with 4336 additions and 59 deletions

View File

@@ -40,6 +40,7 @@ typedef enum {
X(SPL_DROP, "drop", 0, 1, 0, "discard top of stack") \
X(SPL_SWAP, "swap", 0, 2, 2, "swap top two elements") \
X(SPL_PICK, "pick", 1, 0, 1, "push copy of stack[imm] (0=TOS)") \
X(SPL_ROT, "rot", 0, 3, 3, "rotate top three (a b c -- b c a)") \
/* 算术 */ \
X(SPL_ADD, "add", 0, 2, 1, "integer addition") \
X(SPL_SUB, "sub", 0, 2, 1, "integer subtraction") \

View File

@@ -8,6 +8,8 @@
*/
#include "spl_syscall.h"
#include "include/core_vec.h"
#include "spl_ir.h"
#include "spl_vm.h"
#include <stdio.h>
@@ -77,36 +79,36 @@
* OS syscalls
* ================================================================= */
/* os_exit — terminate process with the given exit code */
SYSCALL_1(os_exit, int, (exit(a1), (spl_val_t)0))
/* vm_exit — terminate process with the given exit code */
SYSCALL_1(vm_exit, int, (exit(a1), (spl_val_t)0))
/* os_putchar — write a single character to stdout */
SYSCALL_1(os_putchar, int, putchar(a1))
/* vm_putchar — write a single character to stdout */
SYSCALL_1(vm_putchar, int, putchar(a1))
/* os_getchar — read a single character from stdin */
SYSCALL_0(os_getchar, getchar())
/* vm_getchar — read a single character from stdin */
SYSCALL_0(vm_getchar, getchar())
/* os_putint — print an integer to stdout */
SYSCALL_1(os_putint, int, (fprintf(stdout, "%d", a1), (spl_val_t)0))
/* vm_putint — print an integer to stdout */
SYSCALL_1(vm_putint, int, (fprintf(stdout, "%d", a1), (spl_val_t)0))
/* os_putstr — print a string to stdout (no trailing newline) */
SYSCALL_1(os_putstr, const char *, (fputs(a1, stdout), (spl_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))
/* os_fopen — open a file, returns FILE* as spl_val_t */
SYSCALL_2(os_fopen, const char *, const char *, (uintptr_t)fopen(a1, a2))
/* vm_fopen — open a file, returns FILE* as spl_val_t */
SYSCALL_2(vm_fopen, const char *, const char *, (uintptr_t)fopen(a1, a2))
/* os_fclose — close a file, returns 0 on success */
SYSCALL_1(os_fclose, FILE *, fclose(a1))
/* vm_fclose — close a file, returns 0 on success */
SYSCALL_1(vm_fclose, FILE *, fclose(a1))
/* os_fread — read from file, returns number of items read */
SYSCALL_4(os_fread, void *, size_t, size_t, FILE *, fread(a1, a2, a3, a4))
/* vm_fread — read from file, returns number of items read */
SYSCALL_4(vm_fread, void *, size_t, size_t, FILE *, fread(a1, a2, a3, a4))
/* os_fwrite — write to file, returns number of items written */
SYSCALL_4(os_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4))
/* vm_fwrite — write to file, returns number of items written */
SYSCALL_4(vm_fwrite, const void *, size_t, size_t, FILE *, fwrite(a1, a2, a3, a4))
/* os_fsize — get file size in bytes */
static spl_val_t os_fsize(int nargs, spl_val_t *args) {
CHECK_NARGS("os_fsize", 1);
/* vm_fsize — get file size in bytes */
static spl_val_t vm_fsize(int nargs, spl_val_t *args) {
CHECK_NARGS("vm_fsize", 1);
FILE *f = (FILE *)(uintptr_t)args[0];
long cur = ftell(f);
fseek(f, 0, SEEK_END);
@@ -115,9 +117,9 @@ static spl_val_t os_fsize(int nargs, spl_val_t *args) {
return (spl_val_t)(uintptr_t)sz;
}
/* os_read_file — read entire file into a malloc'd, null-terminated buffer */
static spl_val_t os_read_file(int nargs, spl_val_t *args) {
CHECK_NARGS("os_read_file", 1);
/* 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) {
CHECK_NARGS("vm_read_file", 1);
const char *path = (const char *)(uintptr_t)args[0];
FILE *f = fopen(path, "rb");
if (!f)
@@ -136,23 +138,74 @@ static spl_val_t os_read_file(int nargs, spl_val_t *args) {
return (spl_val_t)(uintptr_t)buf;
}
/* os_alloc — allocate memory (malloc) */
SYSCALL_1(os_alloc, size_t, (uintptr_t)malloc(a1))
/* vm_alloc — allocate memory (malloc) */
SYSCALL_1(vm_alloc, size_t, (uintptr_t)malloc(a1))
/* os_free — free memory */
SYSCALL_1(os_free, void *, (free(a1), (spl_val_t)0))
/* vm_free — free memory */
SYSCALL_1(vm_free, void *, (free(a1), (spl_val_t)0))
/* os_realloc — reallocate memory (realloc) */
SYSCALL_2(os_realloc, void *, size_t, (uintptr_t)realloc(a1, a2))
/* vm_realloc — reallocate memory (realloc) */
SYSCALL_2(vm_realloc, void *, size_t, (uintptr_t)realloc(a1, a2))
/* os_strlen — get string length */
SYSCALL_1(os_strlen, const char *, strlen(a1))
/* vm_strlen — get string length */
SYSCALL_1(vm_strlen, const char *, strlen(a1))
/* os_strcmp — compare two strings */
SYSCALL_2(os_strcmp, const char *, const char *, strcmp(a1, a2))
/* vm_strcmp — compare two strings */
SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2))
/* os_memcpy — copy memory, returns dst */
SYSCALL_3(os_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1))
/* 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) {
(void)args;
if (nargs <= 0) {
return 0;
}
const char *fmt = (const char *)args[0];
usize fmt_len = strlen(fmt);
typedef VEC(char) string_builder_t;
string_builder_t buffer;
vec_init(buffer);
if (nargs <= 1) {
printf("%s", fmt);
return nargs;
}
int arg_idx = 0;
char tmp_buf[32];
memset(tmp_buf, 0, sizeof(tmp_buf));
for (int i = 0; i < fmt_len; ++i) {
if (fmt[i] != '%') {
vec_push(buffer, fmt[i]);
continue;
}
arg_idx += 1;
if (++i >= fmt_len) {
continue;
}
switch (fmt[i]) {
case 'd':
snprintf(tmp_buf, sizeof(tmp_buf), "%zd", args[arg_idx]);
for (int j = 0; j < strlen(tmp_buf); ++j) {
vec_push(buffer, tmp_buf[j]);
}
break;
case 'c':
vec_push(buffer, (char)args[arg_idx]);
break;
case 's':
for (int j = 0; j < strlen((const char *)args[arg_idx]); ++j) {
vec_push(buffer, ((const char *)args[arg_idx])[j]);
}
break;
default:
continue;
}
}
vec_push(buffer, '\0');
printf("%s", buffer.data);
vec_free(buffer);
return nargs;
}
/* =================================================================
* VM syscalls (for comptime — compile-time code execution)
@@ -287,23 +340,24 @@ 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[] = {
/* OS operations */
{"os_exit", 0, os_exit},
{"os_putchar", 0, os_putchar},
{"os_getchar", 0, os_getchar},
{"os_putint", 0, os_putint},
{"os_putstr", 0, os_putstr},
{"os_fopen", 0, os_fopen},
{"os_fclose", 0, os_fclose},
{"os_fread", 0, os_fread},
{"os_fwrite", 0, os_fwrite},
{"os_fsize", 0, os_fsize},
{"os_read_file", 0, os_read_file},
{"os_alloc", 0, os_alloc},
{"os_free", 0, os_free},
{"os_realloc", 0, os_realloc},
{"os_strlen", 0, os_strlen},
{"os_strcmp", 0, os_strcmp},
{"os_memcpy", 0, os_memcpy},
{"vm_exit", 0, vm_exit},
{"vm_putchar", 0, vm_putchar},
{"vm_getchar", 0, vm_getchar},
{"vm_putint", 0, vm_putint},
{"vm_putstr", 0, vm_putstr},
{"vm_fopen", 0, vm_fopen},
{"vm_fclose", 0, vm_fclose},
{"vm_fread", 0, vm_fread},
{"vm_fwrite", 0, vm_fwrite},
{"vm_fsize", 0, vm_fsize},
{"vm_read_file", 0, vm_read_file},
{"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_printf", 0, vm_printf},
/* VM operations (comptime) */
{"vm_new", 0, vm_new},
{"vm_drop", 0, vm_drop},

View File

@@ -50,7 +50,7 @@ static int spl_type_size(spl_type_t t) {
case SPL_ISIZE:
case SPL_USIZE:
case SPL_PTR:
return sizeof(void *) / 8;
return sizeof(void *);
case SPL_TYPE_COUNT:
return 0;
}
@@ -554,18 +554,27 @@ void spl_vm_set_debug(spl_vm_t *vm, int enabled) {
vm->debug = enabled ? 1 : 0;
}
#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) {
if (vm->cp >= vm->config.max_call_depth)
VM_ERROR("CALLI: call stack overflow");
// spl_vm_stackdump(vm, vm->sp);
PUSH(SPL_STACK_CANARY);
/* Shift args right by 1 to create gap for canary at fp-1 */
for (usize i = vm->sp; i >= vm->sp - nargs; --i) {
vm->stacks.data[i] = vm->stacks.data[i - 1];
}
vm->frames.data[vm->cp].saved_sp = vm->sp - nargs - 1;
vm->frames.data[vm->cp].saved_fp = vm->fp;
vm->frames.data[vm->cp].saved_ip = vm->ip;
vm->frames.data[vm->cp].nargs = nargs;
vm->cp++;
vm->ip = addr;
vm->fp = vm->sp - nargs;
/* Transparent canary at fp-1 — invisible to normal LADDR/ST */
if (vm->fp > 0)
vm->stacks.data[vm->fp - 1] = SPL_STACK_CANARY;
STACK_CANARY(vm) = SPL_STACK_CANARY;
// spl_vm_stackdump(vm, vm->sp);
return 0;
}
@@ -670,6 +679,18 @@ int spl_vm_run_once(spl_vm_t *vm) {
break;
}
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];
vm->stacks.data[vm->sp - 3] = _b;
vm->stacks.data[vm->sp - 2] = _c;
vm->stacks.data[vm->sp - 1] = _a;
break;
}
/* ========== Arithmetic ========== */
case SPL_ADD:
ARITH_BINOP(+);
@@ -821,6 +842,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
if (vm->cp <= 0)
VM_ERROR("RET: call stack underflow");
vm->cp--;
intptr_t _saved_sp = vm->frames.data[vm->cp].saved_sp;
intptr_t _saved_fp = vm->frames.data[vm->cp].saved_fp;
intptr_t _saved_ip = vm->frames.data[vm->cp].saved_ip;
/* entry return -> halt */
@@ -828,11 +850,12 @@ int spl_vm_run_once(spl_vm_t *vm) {
vm->exit_code = (int)_retval;
return 1;
}
vm->sp = vm->fp;
vm->sp = _saved_sp;
vm->fp = _saved_fp;
vm->ip = _saved_ip;
if (ins->type != SPL_VOID)
PUSH(_retval);
// spl_vm_stackdump(vm, vm->sp);
break;
}
@@ -933,6 +956,9 @@ int spl_vm_run_once(spl_vm_t *vm) {
VM_ERROR(vm->error_msg);
}
spl_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);
vm->sp -= _nargs;
PUSH(_result);
@@ -969,8 +995,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
/* canary check in debug mode (canary is at fp-1, invisible to compiled code) */
if (vm->debug && vm->fp > 0) {
spl_val_t val = vm->stacks.data[vm->fp - 1];
if (val != SPL_STACK_CANARY) {
if (STACK_CANARY(vm) != SPL_STACK_CANARY) {
snprintf(vm->error_msg, sizeof(vm->error_msg),
"STACK CANARY CORRUPTED at ip=%zd, fp=%zd\n", vm->ip - 1, vm->fp);
VM_ERROR(vm->error_msg);

View File

@@ -10,6 +10,7 @@
#define SPL_STACK_CANARY ((spl_val_t)0xDEADBEEFCAFEBABEull)
typedef struct {
uintptr_t saved_sp;
uintptr_t saved_fp;
uintptr_t saved_ip;
spl_val_t nargs;