stage1 使用切片表达字符串而非C字符串 提供属性系统
This commit is contained in:
1 parent
a64a96f9a4
commit
72ae6d6994
14 files changed
+685
-1256
No files matched your search
+174
-67
@@ -68,6 +68,41 @@ static usize ir_agg_field_off(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_or_add_native(spl_ir2vm_t *ctx, const char *name) {
|
||||
if (!name)
|
||||
return -1;
|
||||
for (usize i = 0; i < vec_size(ctx->prog.natives); ++i) {
|
||||
spl_vm_native_t *n = &vec_at(ctx->prog.natives, i);
|
||||
if (n->name && strcmp(n->name, name) == 0)
|
||||
return (int)i;
|
||||
}
|
||||
spl_vm_native_t nat = {0};
|
||||
nat.name = strdup(name);
|
||||
nat.idx_of_strtab = 0;
|
||||
nat.impl_fn = NULL;
|
||||
vec_push(ctx->prog.natives, nat);
|
||||
return (int)(vec_size(ctx->prog.natives) - 1);
|
||||
}
|
||||
|
||||
static bool fn_check_extern(spl_ir2vm_t *ctx, spl_ir_func_t *f, const char **out_target) {
|
||||
if (out_target)
|
||||
*out_target = NULL;
|
||||
if (!ctx->attr || !f)
|
||||
return false;
|
||||
for (usize i = 0; i < vec_size(f->attrs); ++i) {
|
||||
spl_attr_node_t *a = spl_attr_node(ctx->attr, vec_at(f->attrs, i));
|
||||
if (!a || !a->info)
|
||||
continue;
|
||||
if (strcmp(a->info->name, "extern") != 0)
|
||||
continue;
|
||||
a->consumed_mask |= (1u << SPL_ATTR_STAGE_IR);
|
||||
if (out_target && vec_size(a->args) >= 1 && vec_at(a->args, 0).kind == SPL_ATTR_ARG_STR)
|
||||
*out_target = vec_at(a->args, 0).value.s;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t vm_kind_of(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
|
||||
if (!tn)
|
||||
@@ -217,17 +252,12 @@ static usize node_data_size(spl_ir2vm_t *ctx, const spl_ir_func_t *f, const spl_
|
||||
if (ir_is_aggregate(ctx, node->mem_load.tid))
|
||||
return ir_type_size(ctx, node->mem_load.tid);
|
||||
return 0;
|
||||
case SPL_IR_DBG_PANIC:
|
||||
return sizeof(spl_vm_val_t) * 4; /* TODO: fmt slice + msg slice */
|
||||
case SPL_IR_CONTROL_CALL:
|
||||
if (ir_is_aggregate(ctx, node->control_call.tid))
|
||||
return ir_type_size(ctx, node->control_call.tid);
|
||||
return 0;
|
||||
case SPL_IR_TYPE_CONST: {
|
||||
spl_type_node_t *tn = spl_type_node(ctx->type, node->type_const.tid);
|
||||
if (tn && (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY ||
|
||||
tn->kind == SPL_TYPE_UNION))
|
||||
return ir_type_size(ctx, node->type_const.tid);
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -415,30 +445,17 @@ static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
return;
|
||||
|
||||
if (tn->kind == SPL_TYPE_FN) {
|
||||
usize idx = ip_of(cg);
|
||||
CG_PUSH(cg, SPL_PTR, 0);
|
||||
cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn);
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
return;
|
||||
}
|
||||
isize nat_idx = -1;
|
||||
if (n->type_const.fn > 0)
|
||||
map_get(ctx->extern_native, n->type_const.fn, &nat_idx);
|
||||
|
||||
if (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY || tn->kind == SPL_TYPE_UNION) {
|
||||
const char *bytes = (const char *)n->type_const.ptr_lit;
|
||||
if (!bytes)
|
||||
bytes = "";
|
||||
usize len = strlen(bytes);
|
||||
usize data_idx = (usize)spl_prog_add_data(&ctx->prog, (void *)bytes, len + 1);
|
||||
usize base = vec_at(cg->frame.slots, ref).data_off;
|
||||
usize ptr_off = ir_agg_field_off(ctx, tid, 0);
|
||||
usize len_off = ir_agg_field_off(ctx, tid, 1);
|
||||
|
||||
CG_GADDR(cg, data_idx);
|
||||
cg_store_at(cg, base + ptr_off, SPL_PTR);
|
||||
|
||||
CG_PUSH(cg, SPL_U64, len);
|
||||
cg_store_at(cg, base + len_off, SPL_U64);
|
||||
|
||||
CG_LADDR(cg, base);
|
||||
if (nat_idx >= 0) {
|
||||
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
|
||||
} else {
|
||||
usize idx = ip_of(cg);
|
||||
CG_PUSH(cg, SPL_PTR, 0);
|
||||
cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn);
|
||||
}
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
return;
|
||||
}
|
||||
@@ -506,6 +523,21 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_IR_MEM_GLOBAL_ALLOC: {
|
||||
const spl_ir_node_t *cn = &vec_at(cg->irf->nodes, n->mem_global_alloc.const_node);
|
||||
int idx = 0;
|
||||
if (cn->kind == SPL_IR_TYPE_CONST && cn->type_const.ptr_lit) {
|
||||
usize size = ir_type_size(ctx, cn->type_const.tid);
|
||||
idx = spl_prog_add_data(&ctx->prog, cn->type_const.ptr_lit, size);
|
||||
}
|
||||
if (idx > 0)
|
||||
emit(cg, SPL_GADDR, SPL_VOID, (spl_vm_val_t)idx);
|
||||
else
|
||||
CG_PUSH(cg, SPL_PTR, 0);
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_IR_MEM_LOAD: {
|
||||
spl_type_id_t tid = n->mem_load.tid;
|
||||
if (ir_is_aggregate(ctx, tid)) {
|
||||
@@ -716,43 +748,48 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
}
|
||||
|
||||
case SPL_IR_CONTROL_CALL: {
|
||||
usize nargs = vec_size(n->control_call.params);
|
||||
for (usize i = 0; i < nargs; ++i) {
|
||||
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
}
|
||||
|
||||
bool direct = false;
|
||||
spl_ir_func_ref_t callee_ref = 0;
|
||||
spl_ir_node_ref_t fref = n->control_call.func;
|
||||
if (fref < vec_size(cg->irf->nodes)) {
|
||||
const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref);
|
||||
if (fn_node->kind == SPL_IR_TYPE_CONST) {
|
||||
spl_type_node_t *ftn = spl_type_node(ctx->type, fn_node->type_const.tid);
|
||||
if (ftn && ftn->kind == SPL_TYPE_FN) {
|
||||
usize idx = ip_of(cg);
|
||||
CG_PUSH(cg, SPL_PTR, 0);
|
||||
cg_add_fix(cg, idx, FIX_FNADDR, 0, fn_node->type_const.fn);
|
||||
emit(cg, SPL_CALL, SPL_VOID, nargs);
|
||||
direct = true;
|
||||
}
|
||||
}
|
||||
if (fn_node->kind == SPL_IR_TYPE_CONST)
|
||||
callee_ref = fn_node->type_const.fn;
|
||||
}
|
||||
if (!direct)
|
||||
emit(cg, SPL_HALT, SPL_VOID, 0);
|
||||
|
||||
spl_type_id_t rtid = n->control_call.tid;
|
||||
if (ir_is_aggregate(ctx, rtid)) {
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
usize data = vec_at(cg->frame.slots, ref).data_off;
|
||||
cg_copy_agg(cg, ptr_slot(vec_at(cg->frame.slots, ref).result_off), direct_data(data),
|
||||
rtid);
|
||||
CG_LADDR(cg, data);
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
isize nat_idx = -1;
|
||||
if (callee_ref > 0)
|
||||
map_get(ctx->extern_native, callee_ref, &nat_idx);
|
||||
|
||||
usize nargs = vec_size(n->control_call.params);
|
||||
|
||||
if (nat_idx >= 0) {
|
||||
for (usize i = 0; i < nargs; ++i) {
|
||||
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
}
|
||||
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx);
|
||||
emit(cg, SPL_NCALL, SPL_VOID, (spl_vm_val_t)nargs);
|
||||
|
||||
uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
|
||||
if (rk == SPL_VOID)
|
||||
emit(cg, SPL_DROP, SPL_VOID, 0); /* NCALL 总是 push 一个结果 */
|
||||
else
|
||||
cg_store_slot(cg, ref, rk);
|
||||
} else {
|
||||
uint8_t rk = vm_kind_of(ctx, rtid);
|
||||
for (usize i = 0; i < nargs; ++i) {
|
||||
spl_ir_node_ref_t pref = vec_at(n->control_call.params, i);
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
}
|
||||
cg_load_slot(cg, fref, SPL_PTR);
|
||||
emit(cg, SPL_CALL, SPL_VOID, (spl_vm_val_t)nargs);
|
||||
|
||||
uint8_t rk = vm_kind_of(ctx, n->control_call.tid);
|
||||
if (rk != SPL_VOID)
|
||||
cg_store_slot(cg, ref, rk);
|
||||
}
|
||||
@@ -761,7 +798,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
|
||||
case SPL_IR_CONTROL_UNREACHABLE:
|
||||
case SPL_IR_CONTROL_TRAP:
|
||||
emit(cg, SPL_HALT, SPL_VOID, 0);
|
||||
emit(cg, SPL_HALT, SPL_VOID, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -817,9 +854,18 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
case SPL_IR_ARITH_NEG:
|
||||
cg_unop(cg, ref, n, SPL_NEG);
|
||||
break;
|
||||
case SPL_IR_ARITH_NOT:
|
||||
cg_unop(cg, ref, n, SPL_NOT);
|
||||
case SPL_IR_ARITH_NOT: {
|
||||
spl_type_node_t *tn = spl_type_node(cg->ctx->type, n->arith.tid);
|
||||
if (tn && tn->kind == SPL_TYPE_BOOL) {
|
||||
cg_load_slot(cg, n->arith.left, SPL_BOOL);
|
||||
CG_PUSH(cg, SPL_U8, 0);
|
||||
CG_OP(cg, SPL_EQ, SPL_U8);
|
||||
cg_store_slot(cg, ref, SPL_BOOL);
|
||||
} else {
|
||||
cg_unop(cg, ref, n, SPL_NOT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPL_IR_ARITH_ABS:
|
||||
break;
|
||||
|
||||
@@ -869,6 +915,7 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
break;
|
||||
|
||||
case SPL_IR_MEM_ALLOCA:
|
||||
case SPL_IR_MEM_GLOBAL_ALLOC:
|
||||
case SPL_IR_MEM_LOAD:
|
||||
case SPL_IR_MEM_STORE:
|
||||
case SPL_IR_MEM_OFFSET:
|
||||
@@ -898,6 +945,39 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
cg_control(cg, ref, n);
|
||||
break;
|
||||
|
||||
case SPL_IR_DBG_PANIC: {
|
||||
spl_ir2vm_t *ctx = cg->ctx;
|
||||
usize data = vec_at(cg->frame.slots, ref).data_off;
|
||||
|
||||
int msg_idx = spl_prog_add_data(&ctx->prog, (void *)n->dbg_panic.msg, n->dbg_panic.len);
|
||||
int fmt_idx = spl_prog_add_data(&ctx->prog, "%s", 2);
|
||||
if (msg_idx <= 0 || fmt_idx <= 0)
|
||||
break;
|
||||
|
||||
/* fmt slice = {ptr, len=2} 写到 data+0 */
|
||||
CG_GADDR(cg, (spl_vm_val_t)fmt_idx);
|
||||
cg_store_at(cg, data + 0, SPL_PTR);
|
||||
CG_PUSH(cg, SPL_U64, 2);
|
||||
cg_store_at(cg, data + 8, SPL_U64);
|
||||
|
||||
/* msg slice = {ptr, len} 写到 data+16 */
|
||||
CG_GADDR(cg, (spl_vm_val_t)msg_idx);
|
||||
cg_store_at(cg, data + 16, SPL_PTR);
|
||||
CG_PUSH(cg, SPL_U64, n->dbg_panic.len);
|
||||
cg_store_at(cg, data + 24, SPL_U64);
|
||||
|
||||
/* push fmt slice 指针,push msg slice 指针 */
|
||||
CG_LADDR(cg, data + 0);
|
||||
CG_LADDR(cg, data + 16);
|
||||
|
||||
/* NCALL vm_printf(2) */
|
||||
int nat = get_or_add_native(ctx, "vm_printf");
|
||||
CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat);
|
||||
emit(cg, SPL_NCALL, SPL_VOID, 2);
|
||||
emit(cg, SPL_DROP, SPL_VOID, 0); /* 丢弃返回值 */
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_IR_DBG_BREAKPOINT:
|
||||
emit(cg, SPL_BK, SPL_VOID, 0);
|
||||
break;
|
||||
@@ -963,13 +1043,23 @@ static usize translate_function(spl_ir2vm_t *ctx, spl_ir_func_ref_t fid, fix_vec
|
||||
return func_ip;
|
||||
}
|
||||
|
||||
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type) {
|
||||
static usize spl_map_hash(usize k) { return MAP_HASH_INT(k); }
|
||||
static int spl_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
|
||||
|
||||
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
|
||||
const spl_attr_t *attr) {
|
||||
Assert(ir != NULL && type != NULL && attr != NULL);
|
||||
ctx->ir = ir;
|
||||
ctx->type = type;
|
||||
ctx->attr = attr;
|
||||
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
|
||||
spl_prog_init(&ctx->prog);
|
||||
}
|
||||
|
||||
void spl_ir2vm_drop(spl_ir2vm_t *ctx) { spl_prog_drop(&ctx->prog); }
|
||||
void spl_ir2vm_drop(spl_ir2vm_t *ctx) {
|
||||
spl_prog_drop(&ctx->prog);
|
||||
map_free(ctx->extern_native);
|
||||
}
|
||||
|
||||
int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref) {
|
||||
fix_vec_t all_fixups;
|
||||
@@ -984,13 +1074,30 @@ int spl_ir2vm_run(spl_ir2vm_t *ctx) {
|
||||
if (n <= 1)
|
||||
return 0;
|
||||
|
||||
/* Pass 1:扫描所有 fn,把 extern 的登记到 map 里 */
|
||||
for (spl_ir_func_ref_t i = 1; i < n; ++i) {
|
||||
spl_ir_func_t *irf = spl_ir_func((spl_ir_t *)ctx->ir, i);
|
||||
if (!irf)
|
||||
continue;
|
||||
if (fn_check_extern(ctx, irf, NULL)) {
|
||||
int nat_idx = get_or_add_native(ctx, irf->name);
|
||||
map_put(ctx->extern_native, i, (isize)nat_idx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2:翻译非 extern 的函数 */
|
||||
usize *fid_ip = calloc(n, sizeof(usize));
|
||||
fix_vec_t all_fixups;
|
||||
vec_init(all_fixups);
|
||||
|
||||
for (spl_ir_func_ref_t i = 1; i < n; ++i)
|
||||
for (spl_ir_func_ref_t i = 1; i < n; ++i) {
|
||||
isize dummy = -1;
|
||||
if (map_get(ctx->extern_native, i, &dummy))
|
||||
continue;
|
||||
fid_ip[i] = translate_function(ctx, i, &all_fixups);
|
||||
}
|
||||
|
||||
/* FNADDR 回填 */
|
||||
for (usize i = 0; i < vec_size(all_fixups); ++i) {
|
||||
fix_t *fx = &vec_at(all_fixups, i);
|
||||
if (fx->kind != FIX_FNADDR)
|
||||
|
||||
Reference in new issue
Block a user