stage0 新增内存复制指令 重构vm交互

This commit is contained in:
zzy committed 2026-09-29 21:11:15 +08:00
1 parent 0b8f649818
commit 40cffa9cb5
22 files changed
+626 -158

No files matched your search

+1
View File
@@ -97,6 +97,7 @@ typedef enum {
/* 间接内存访问 */ \
X(SPL_LOAD, "load", 0, 1, 1, "load sizeof(type)-bits zero-extended") \
X(SPL_STORE, "store", 0, 2, 0, "store low sizeof(type)-bits") \
X(SPL_MEMCPY, "memcpy", 0, 3, 0, "copy n bytes: pop dst, src, n (VM address space)") \
/* 原生接口 */ \
X(SPL_NCALL, "ncall", 1, 0, 1, "call native function by index") \
X(SPL_NLIB, "nlib", 1, 0, 0, "dlopen library (name idx)") \
-28
View File
@@ -87,32 +87,4 @@ SPL_FN u64 vm_timestamp(u64 kind) {
#define SPL_VM_EMBED_IMPLIMENTATION
#include "spl_vm_embed.h"
/* 配置层外部函数处理器(native 端):把 nested VM 未解析的 native 按名分发到
* 编译器生成的 `ct_*` 函数(表由 ir2c 生成,见 stage2/ir2c.spl)。 */
extern void *spl_ct_lookup(const char *name);
typedef spl_vm_val_t (*spl_native_ct_fn_t)(void *, spl_vm_val_t, spl_vm_val_t, spl_vm_val_t);
SPL_FN spl_vm_val_t spl_native_foreign(spl_vm_t *vm, const spl_vm_call_t *call, void *user) {
void *fn;
spl_vm_val_t a0 = 0, a1 = 0;
(void)vm;
if (!call)
return 0;
fn = spl_ct_lookup(call->name);
if (!fn)
return 0;
if (call->nargs > 0)
a0 = call->args[0];
if (call->nargs > 1)
a1 = call->args[1];
/* ct_* 统一形状:返回 u64,参数 (ctx, u64, u64);多余参数被忽略。 */
return ((spl_native_ct_fn_t)fn)(user, a0, a1, 0);
}
SPL_FN void vm_set_foreign(void *p, unsigned long long handler, void *ctx) {
(void)handler;
spl_vm_set_foreign((spl_vm_t *)p, spl_native_foreign, ctx);
}
#endif /* __SPL_RT_H__ */
+58 -33
View File
@@ -615,33 +615,51 @@ static spl_vm_val_t vm_timestamp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
* nested-VM syscalls
* ================================================================= */
/* ---- 配置层的“外部函数处理器”:把某个 VM 未解析的 native 交给调用者 VM。
* 这是配置策略,不属于 VM 库 API;VM 本身只有通用 foreign 钩子。 ---- */
/* 通用双向桥(配置层策略,非 VM 平台 API):
* 在子 VM 上安装「未解析 native 处理器」,把子 VM 的未解析调用按名转发到
* 宿主(调用者)VM 中由 `entry` 指定的函数。宿主函数收到:
* (ctx, name_off, name_len, nested_vm, arg_base, nargs)
* 平台/C 侧**纯转发**:不复制实参、不限元数、不了解类型;聚合读写由宿主用
* vm_stack_get / vm_mem_read / vm_mem_alloc / vm_mem_write 自行完成。
* `entry` 由宿主显式给出,平台不预设任何函数名。 */
typedef struct {
spl_vm_t *caller;
spl_vm_t *host;
void *ctx;
} spl_foreign_t;
char entry[128];
} spl_bridge_t;
static spl_vm_val_t spl_foreign_reenter(spl_vm_t *vm, const spl_vm_call_t *call, void *user) {
spl_foreign_t *f = (spl_foreign_t *)user;
spl_vm_val_t tmp[20];
spl_vm_call_t c2;
int i;
(void)vm;
if (!f || !f->caller || !call || !call->name)
static spl_vm_val_t spl_bridge_forward(spl_vm_t *nested, const spl_vm_call_t *call, void *user) {
spl_bridge_t *b = (spl_bridge_t *)user;
spl_vm_val_t name_off;
spl_vm_val_t args[6];
spl_vm_call_t back;
usize n;
usize arg_base;
if (!b || !b->host || !call || !call->name || b->entry[0] == '\0')
return 0;
if (call->nargs + 1 > (usize)(sizeof(tmp) / sizeof(tmp[0])))
n = strlen(call->name);
/* 名拷进宿主 VM 内存,宿主按偏移读取。 */
name_off = spl_vm_mem_alloc(b->host, n + 1);
if (!name_off)
return 0;
tmp[0] = (spl_vm_val_t)(uintptr_t)f->ctx;
for (i = 0; i < (int)call->nargs; i++)
tmp[1 + i] = call->args ? call->args[i] : 0;
c2.name = call->name;
c2.args = tmp;
c2.nargs = call->nargs + 1;
c2.ret = 0;
if (spl_vm_invoke(f->caller, &c2) != 0)
if (spl_vm_mem_write(b->host, name_off, call->name, n + 1) != 0)
return 0;
return c2.ret;
arg_base = spl_vm_call_arg_base(nested, call);
if (arg_base == (usize)-1)
return 0;
args[0] = (spl_vm_val_t)(uintptr_t)b->ctx;
args[1] = name_off;
args[2] = (spl_vm_val_t)n;
args[3] = (spl_vm_val_t)(uintptr_t)nested;
args[4] = (spl_vm_val_t)arg_base;
args[5] = (spl_vm_val_t)call->nargs;
back.name = b->entry;
back.args = args;
back.nargs = 6;
back.ret = 0;
if (spl_vm_invoke(b->host, &back) != 0)
return 0;
return back.ret;
}
static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
@@ -655,25 +673,32 @@ static spl_vm_val_t vm_new(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
return (spl_vm_val_t)(uintptr_t)vm;
}
/* 配置入口:vm_set_foreign(vm, handler, ctx)。handler=0:把未解析 native 重入
* 当前调用者(_vm),ctx 透传前置。名与语义由配置层定义;VM 库不认识 foreign handler。 */
/* vm_set_foreign(vm, entry, ctx):宿主显式指定处理器函数名。 */
static spl_vm_val_t sc_vm_set_foreign(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
spl_vm_t *vm;
spl_foreign_t *f;
spl_bridge_t *b;
const spl_vm_val_t *entry;
const char *eptr;
usize elen;
CHECK_NARGS("vm_set_foreign", 3);
vm = (spl_vm_t *)(uintptr_t)args[0];
if (!vm || !_vm)
return -1;
if (args[1] != 0) /* 仅注册 handler 0(重入调用者) */
entry = (const spl_vm_val_t *)VM_XN(_vm, args[1], 2 * sizeof(spl_vm_val_t));
if (!entry)
return -1;
if (vm->foreign == spl_foreign_reenter && vm->foreign_ctx)
free(vm->foreign_ctx);
f = (spl_foreign_t *)malloc(sizeof(*f));
if (!f)
eptr = (const char *)VM_X(_vm, entry[0]);
elen = (usize)entry[1];
if (!eptr || elen == 0 || elen >= sizeof(((spl_bridge_t *)0)->entry))
return -1;
f->caller = _vm;
f->ctx = (void *)(uintptr_t)args[2];
spl_vm_set_foreign(vm, spl_foreign_reenter, f);
b = (spl_bridge_t *)malloc(sizeof(*b));
if (!b)
return -1;
b->host = _vm;
b->ctx = (void *)(uintptr_t)args[2];
memcpy(b->entry, eptr, elen);
b->entry[elen] = '\0';
spl_vm_set_foreign(vm, spl_bridge_forward, b);
return 0;
}
@@ -683,7 +708,7 @@ static spl_vm_val_t vm_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
spl_vm_t *vm = (spl_vm_t *)(uintptr_t)args[0];
if (!vm)
return 0;
if (vm->foreign == spl_foreign_reenter && vm->foreign_ctx)
if (vm->foreign == spl_bridge_forward && vm->foreign_ctx)
free(vm->foreign_ctx);
if (vm->prog) {
spl_prog_drop(vm->prog);
+23
View File
@@ -785,6 +785,14 @@ int spl_vm_stack_set(spl_vm_t *vm, usize index, spl_vm_val_t val) {
return 0;
}
usize spl_vm_call_arg_base(spl_vm_t *vm, const spl_vm_call_t *call) {
if (!vm || !call || !call->args || !vm->stacks.data)
return (usize)-1;
if (call->args < vm->stacks.data)
return (usize)-1;
return (usize)(call->args - vm->stacks.data);
}
spl_vm_val_t spl_vm_mem_alloc(spl_vm_t *vm, usize size) { return spl_vm_asp_alloc(vm, size); }
int spl_vm_mem_read(spl_vm_t *vm, spl_vm_val_t off, void *dst, usize n) {
@@ -1358,6 +1366,7 @@ static int vm_loop(spl_vm_t *vm, size_t limit) {
DT(SPL_CALLI), DT(SPL_RET), DT(SPL_ALLOC),
DT(SPL_LADDR), DT(SPL_GADDR), DT(SPL_LOAD),
DT(SPL_STORE), DT(SPL_NCALL), DT(SPL_NLIB),
DT(SPL_MEMCPY),
DT(SPL_BK), DT(SPL_DBG), [SPL_ERROR] = &&L_default,
};
@@ -1679,6 +1688,20 @@ L_SPL_STORE:
memcpy(_addr, &_v, spl_type_size(ins->type));
DISPATCH();
}
L_SPL_MEMCPY:
{
spl_vm_val_t _n = POP();
spl_vm_val_t _src = POP();
spl_vm_val_t _dst = POP();
if (_n) {
void *_d = spl_vm_xlate(vm, _dst, (usize)_n);
void *_s = spl_vm_xlate(vm, _src, (usize)_n);
if (!_d || !_s)
VM_ERROR("MEMCPY: invalid address");
memmove(_d, _s, (usize)_n);
}
DISPATCH();
}
/* ========== Type Conversion ========== */
L_SPL_TRUNC:
+3
View File
@@ -127,6 +127,9 @@ usize spl_vm_sp(spl_vm_t *vm);
usize spl_vm_fp(spl_vm_t *vm);
spl_vm_val_t spl_vm_stack_get(spl_vm_t *vm, usize index);
int spl_vm_stack_set(spl_vm_t *vm, usize index, spl_vm_val_t val);
/* 本次调用实参在 VM 栈中的起始下标(外部处理器可按需用 stack_get 逐个读取,
* 无需在 C 侧了解参数类型/元数上限)。失败返回 (usize)-1。 */
usize spl_vm_call_arg_base(spl_vm_t *vm, const spl_vm_call_t *call);
spl_vm_val_t spl_vm_mem_alloc(spl_vm_t *vm, usize size);
int spl_vm_mem_read(spl_vm_t *vm, spl_vm_val_t off, void *dst, usize n);
int spl_vm_mem_write(spl_vm_t *vm, spl_vm_val_t off, const void *src, usize n);