stage0 新增内存复制指令 重构vm交互
This commit is contained in:
1 parent
0b8f649818
commit
40cffa9cb5
22 files changed
+626
-158
No files matched your search
@@ -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)") \
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user