stage2 大量优化代码使其自举编译时间大幅缩短
This commit is contained in:
1 parent
e02b0c633a
commit
846f441e3a
38 files changed
+2418
-835
No files matched your search
+319
-34
@@ -344,6 +344,13 @@ typedef struct {
|
||||
frame_layout_t frame;
|
||||
VEC(usize) node_ip;
|
||||
fix_vec_t *fixups;
|
||||
/* 块内栈化(opt) */
|
||||
int opt;
|
||||
uint8_t *stk_loc; /* per node: 1 = 值当前在操作数栈上 */
|
||||
usize *stk_pos; /* 在虚拟栈中的位置 */
|
||||
usize *use_left; /* 剩余使用次数 */
|
||||
usize *at_pos; /* 每个栈位置对应的 node ref */
|
||||
usize tracked; /* 当前栈上被跟踪的值个数 */
|
||||
} cgen_t;
|
||||
|
||||
static void emit(cgen_t *cg, uint8_t op, uint8_t ty, spl_vm_val_t imm) {
|
||||
@@ -378,6 +385,240 @@ static void cg_store_at(cgen_t *cg, usize addr, uint8_t k) {
|
||||
CG_STORE(cg, k);
|
||||
}
|
||||
|
||||
/* ---------- 块内栈化(opt)辅助 ---------- */
|
||||
|
||||
static uint8_t node_result_kind(cgen_t *cg, usize ref) {
|
||||
const spl_ir_node_t *n = &vec_at(cg->irf->nodes, ref);
|
||||
return vm_kind_of(cg->ctx, ir_result_tid(cg->ctx, n));
|
||||
}
|
||||
|
||||
static bool node_stackable(cgen_t *cg, const spl_ir_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_IR_ARITH_ADD:
|
||||
case SPL_IR_ARITH_SUB:
|
||||
case SPL_IR_ARITH_MUL:
|
||||
case SPL_IR_ARITH_DIV:
|
||||
case SPL_IR_ARITH_REM:
|
||||
case SPL_IR_ARITH_NEG:
|
||||
case SPL_IR_ARITH_AND:
|
||||
case SPL_IR_ARITH_OR:
|
||||
case SPL_IR_ARITH_XOR:
|
||||
case SPL_IR_ARITH_SHL:
|
||||
case SPL_IR_ARITH_SHR:
|
||||
case SPL_IR_ARITH_NOT:
|
||||
case SPL_IR_CMP_EQ:
|
||||
case SPL_IR_CMP_NE:
|
||||
case SPL_IR_CMP_LT:
|
||||
case SPL_IR_CMP_LE:
|
||||
case SPL_IR_CMP_GT:
|
||||
case SPL_IR_CMP_GE:
|
||||
case SPL_IR_CAST_TRUNC:
|
||||
case SPL_IR_CAST_ZEXT:
|
||||
case SPL_IR_CAST_SEXT:
|
||||
case SPL_IR_CAST_FEXT:
|
||||
case SPL_IR_CAST_FTRUNC:
|
||||
case SPL_IR_CAST_BITCAST:
|
||||
case SPL_IR_CAST_PTR2INT:
|
||||
case SPL_IR_CAST_INT2PTR:
|
||||
case SPL_IR_CAST_BOOL2INT:
|
||||
case SPL_IR_CASE_INT2FLOAT:
|
||||
case SPL_IR_CASE_FLOAT2INT:
|
||||
case SPL_IR_TYPE_CONST: {
|
||||
spl_type_node_t *tn = spl_type_node(cg->ctx->type, n->type_const.tid);
|
||||
return tn && tn->kind != SPL_TYPE_UNIT;
|
||||
}
|
||||
case SPL_IR_TYPE_BITSIZEOF:
|
||||
case SPL_IR_TYPE_SIZEOF:
|
||||
case SPL_IR_TYPE_ALIGNOF:
|
||||
case SPL_IR_TYPE_OFFSETOF:
|
||||
case SPL_IR_TYPE_FIELD_COUNT:
|
||||
case SPL_IR_MEM_OFFSET:
|
||||
case SPL_IR_MEM_FIELD_PTR:
|
||||
return true;
|
||||
case SPL_IR_MEM_LOAD:
|
||||
return !ir_is_aggregate(cg->ctx, n->mem_load.tid);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* 该节点必须使用槽(直接按槽偏移读写 / 控制转移 / 聚合数据),生成前需 flush。 */
|
||||
static bool node_needs_slots(cgen_t *cg, const spl_ir_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_IR_MEM_ALLOCA:
|
||||
case SPL_IR_MEM_GLOBAL_ALLOC:
|
||||
case SPL_IR_MEM_COPY:
|
||||
case SPL_IR_MEM_SET:
|
||||
case SPL_IR_AGG_CONSTRUCT:
|
||||
case SPL_IR_AGG_EXTRACT:
|
||||
case SPL_IR_AGG_INSERT:
|
||||
case SPL_IR_CONTROL_SELECT:
|
||||
case SPL_IR_CONTROL_BR:
|
||||
case SPL_IR_CONTROL_JMP:
|
||||
case SPL_IR_CONTROL_RET:
|
||||
case SPL_IR_CONTROL_UNREACHABLE:
|
||||
case SPL_IR_CONTROL_TRAP:
|
||||
case SPL_IR_DBG_PANIC:
|
||||
case SPL_IR_DBG_BREAKPOINT:
|
||||
return true;
|
||||
case SPL_IR_MEM_LOAD:
|
||||
return ir_is_aggregate(cg->ctx, n->mem_load.tid);
|
||||
case SPL_IR_MEM_STORE:
|
||||
return ir_is_aggregate(cg->ctx, n->mem_store.tid);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* 取操作数到 TOS:若在栈上就 PICK,否则从槽 load。j = 本节点已压入的操作数个数。 */
|
||||
static void cg_operand(cgen_t *cg, usize ref, uint8_t k, usize j) {
|
||||
if (cg->opt) {
|
||||
if (cg->use_left[ref] > 0)
|
||||
cg->use_left[ref]--;
|
||||
if (cg->stk_loc[ref]) {
|
||||
/* 始终复制一份到 TOS,绝不消费栈上的“被跟踪原值”,否则位置模型失效。 */
|
||||
usize dist = cg->tracked + j - 1 - cg->stk_pos[ref];
|
||||
emit(cg, SPL_PICK, SPL_VOID, dist);
|
||||
return;
|
||||
}
|
||||
}
|
||||
cg_load_slot(cg, ref, k);
|
||||
}
|
||||
|
||||
/* 节点结果:若仍会被使用则留在栈上,否则 DROP。 */
|
||||
static void cg_result(cgen_t *cg, usize ref, uint8_t k) {
|
||||
if (cg->opt) {
|
||||
if (cg->use_left[ref] > 0) {
|
||||
cg->stk_loc[ref] = 1;
|
||||
cg->stk_pos[ref] = cg->tracked;
|
||||
cg->at_pos[cg->tracked] = ref;
|
||||
cg->tracked++;
|
||||
} else {
|
||||
emit(cg, SPL_DROP, SPL_VOID, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
cg_store_slot(cg, ref, k);
|
||||
}
|
||||
|
||||
/* 把栈上仍存活的值溢出回各自槽(TOS 起),死值 DROP;清空跟踪。 */
|
||||
static void cg_flush(cgen_t *cg) {
|
||||
if (!cg->opt)
|
||||
return;
|
||||
while (cg->tracked > 0) {
|
||||
cg->tracked--;
|
||||
usize r = cg->at_pos[cg->tracked];
|
||||
cg->stk_loc[r] = 0;
|
||||
if (cg->use_left[r] > 0) {
|
||||
uint8_t k = node_result_kind(cg, r);
|
||||
cg_store_slot(cg, r, k);
|
||||
} else {
|
||||
emit(cg, SPL_DROP, SPL_VOID, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 统计被引用次数(所有节点载荷中的 node ref)。 */
|
||||
static void count_ref(cgen_t *cg, usize r) {
|
||||
if (r != 0 && r < vec_size(cg->irf->nodes))
|
||||
cg->use_left[r]++;
|
||||
}
|
||||
static void count_refs_vec(cgen_t *cg, const spl_ir_node_ref_vec_t *v) {
|
||||
for (usize i = 0; i < vec_size(*v); i++)
|
||||
count_ref(cg, vec_at(*v, i));
|
||||
}
|
||||
static void count_refs(cgen_t *cg, const spl_ir_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_IR_ARITH_ADD: case SPL_IR_ARITH_SUB: case SPL_IR_ARITH_MUL:
|
||||
case SPL_IR_ARITH_DIV: case SPL_IR_ARITH_REM: case SPL_IR_ARITH_NEG:
|
||||
case SPL_IR_ARITH_ABS: case SPL_IR_ARITH_AND: case SPL_IR_ARITH_OR:
|
||||
case SPL_IR_ARITH_XOR: case SPL_IR_ARITH_SHL: case SPL_IR_ARITH_SHR:
|
||||
case SPL_IR_ARITH_NOT:
|
||||
count_ref(cg, n->arith.left);
|
||||
count_ref(cg, n->arith.right);
|
||||
break;
|
||||
case SPL_IR_CMP_EQ: case SPL_IR_CMP_NE: case SPL_IR_CMP_LT:
|
||||
case SPL_IR_CMP_LE: case SPL_IR_CMP_GT: case SPL_IR_CMP_GE:
|
||||
count_ref(cg, n->cmp.a);
|
||||
count_ref(cg, n->cmp.b);
|
||||
break;
|
||||
case SPL_IR_CAST_TRUNC: case SPL_IR_CAST_ZEXT: case SPL_IR_CAST_SEXT:
|
||||
case SPL_IR_CAST_FEXT: case SPL_IR_CAST_FTRUNC: case SPL_IR_CAST_BITCAST:
|
||||
case SPL_IR_CAST_PTR2INT: case SPL_IR_CAST_INT2PTR: case SPL_IR_CAST_BOOL2INT:
|
||||
case SPL_IR_CASE_INT2FLOAT: case SPL_IR_CASE_FLOAT2INT:
|
||||
count_ref(cg, n->cast.val);
|
||||
break;
|
||||
case SPL_IR_MEM_ALLOCA:
|
||||
count_ref(cg, n->mem_alloc.count);
|
||||
break;
|
||||
case SPL_IR_MEM_GLOBAL_ALLOC:
|
||||
count_ref(cg, n->mem_global_alloc.const_node);
|
||||
break;
|
||||
case SPL_IR_MEM_LOAD:
|
||||
count_ref(cg, n->mem_load.ptr);
|
||||
break;
|
||||
case SPL_IR_MEM_STORE:
|
||||
count_ref(cg, n->mem_store.ptr);
|
||||
count_ref(cg, n->mem_store.val);
|
||||
break;
|
||||
case SPL_IR_MEM_OFFSET:
|
||||
count_ref(cg, n->mem_offset.ptr);
|
||||
count_ref(cg, n->mem_offset.offset);
|
||||
break;
|
||||
case SPL_IR_MEM_FIELD_PTR:
|
||||
count_ref(cg, n->mem_field_ptr.agg);
|
||||
break;
|
||||
case SPL_IR_MEM_COPY:
|
||||
count_ref(cg, n->mem_copy.dst);
|
||||
count_ref(cg, n->mem_copy.src);
|
||||
count_ref(cg, n->mem_copy.size);
|
||||
break;
|
||||
case SPL_IR_MEM_SET:
|
||||
count_ref(cg, n->mem_set.dst);
|
||||
count_ref(cg, n->mem_set.val);
|
||||
count_ref(cg, n->mem_set.size);
|
||||
break;
|
||||
case SPL_IR_TYPE_OFFSETOF:
|
||||
count_ref(cg, n->ir_offsetof.field_idx);
|
||||
break;
|
||||
case SPL_IR_AGG_CONSTRUCT:
|
||||
count_refs_vec(cg, &n->agg_construct.fields);
|
||||
break;
|
||||
case SPL_IR_AGG_EXTRACT:
|
||||
count_ref(cg, n->agg_extract.val);
|
||||
break;
|
||||
case SPL_IR_AGG_INSERT:
|
||||
count_ref(cg, n->agg_insert.agg);
|
||||
count_ref(cg, n->agg_insert.field);
|
||||
break;
|
||||
case SPL_IR_CONTROL_SELECT:
|
||||
count_ref(cg, n->control_select.cond);
|
||||
count_ref(cg, n->control_select.true_val);
|
||||
count_ref(cg, n->control_select.false_val);
|
||||
break;
|
||||
case SPL_IR_CONTROL_BR:
|
||||
count_ref(cg, n->control_br.cond);
|
||||
count_ref(cg, n->control_br.true_label);
|
||||
count_ref(cg, n->control_br.false_label);
|
||||
break;
|
||||
case SPL_IR_CONTROL_JMP:
|
||||
count_ref(cg, n->control_jmp.label);
|
||||
break;
|
||||
case SPL_IR_CONTROL_CALL:
|
||||
count_ref(cg, n->control_call.func);
|
||||
count_refs_vec(cg, &n->control_call.params);
|
||||
break;
|
||||
case SPL_IR_CONTROL_PARAM:
|
||||
count_ref(cg, n->control_param.idx);
|
||||
break;
|
||||
case SPL_IR_CONTROL_RET:
|
||||
count_ref(cg, n->control_ret.val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
bool indirect;
|
||||
usize off;
|
||||
@@ -439,25 +680,25 @@ static void cg_add_fix(cgen_t *cg, usize ins_idx, fix_kind_t kind, spl_ir_node_r
|
||||
|
||||
static void cg_binop(cgen_t *cg, usize ref, const spl_ir_node_t *n, uint8_t op) {
|
||||
uint8_t k = vm_kind_of(cg->ctx, n->arith.tid);
|
||||
cg_load_slot(cg, n->arith.left, k);
|
||||
cg_load_slot(cg, n->arith.right, k);
|
||||
cg_operand(cg, n->arith.left, k, 0);
|
||||
cg_operand(cg, n->arith.right, k, 1);
|
||||
CG_OP(cg, op, k);
|
||||
cg_store_slot(cg, ref, k);
|
||||
cg_result(cg, ref, k);
|
||||
}
|
||||
|
||||
static void cg_unop(cgen_t *cg, usize ref, const spl_ir_node_t *n, uint8_t op) {
|
||||
uint8_t k = vm_kind_of(cg->ctx, n->arith.tid);
|
||||
cg_load_slot(cg, n->arith.left, k);
|
||||
cg_operand(cg, n->arith.left, k, 0);
|
||||
CG_OP(cg, op, k);
|
||||
cg_store_slot(cg, ref, k);
|
||||
cg_result(cg, ref, k);
|
||||
}
|
||||
|
||||
static void cg_cmp(cgen_t *cg, usize ref, const spl_ir_node_t *n, uint8_t op) {
|
||||
uint8_t k = vm_kind_of(cg->ctx, n->cmp.tid);
|
||||
cg_load_slot(cg, n->cmp.a, k);
|
||||
cg_load_slot(cg, n->cmp.b, k);
|
||||
cg_operand(cg, n->cmp.a, k, 0);
|
||||
cg_operand(cg, n->cmp.b, k, 1);
|
||||
CG_OP(cg, op, k);
|
||||
cg_store_slot(cg, ref, SPL_BOOL);
|
||||
cg_result(cg, ref, SPL_BOOL);
|
||||
}
|
||||
|
||||
static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
@@ -479,7 +720,7 @@ static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
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);
|
||||
cg_result(cg, ref, SPL_PTR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -507,7 +748,7 @@ static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
break;
|
||||
}
|
||||
CG_PUSH(cg, k, imm);
|
||||
cg_store_slot(cg, ref, k);
|
||||
cg_result(cg, ref, k);
|
||||
}
|
||||
|
||||
static void cg_cast(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
@@ -520,7 +761,7 @@ static void cg_cast(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
uint8_t fk = vm_kind_of(ctx, n->cast.from_tid);
|
||||
uint8_t tk = vm_kind_of(ctx, n->cast.to_tid);
|
||||
|
||||
cg_load_slot(cg, n->cast.val, fk);
|
||||
cg_operand(cg, n->cast.val, fk, 0);
|
||||
|
||||
if (ft->kind == SPL_TYPE_INT && tt->kind == SPL_TYPE_INT) {
|
||||
usize fb = ft->int_type.bits;
|
||||
@@ -533,7 +774,7 @@ static void cg_cast(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
emit(cg, SPL_ZEXT, SPL_VOID, 1);
|
||||
}
|
||||
|
||||
cg_store_slot(cg, ref, tk);
|
||||
cg_result(cg, ref, tk);
|
||||
}
|
||||
|
||||
static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
@@ -571,9 +812,9 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
} else {
|
||||
uint8_t k = vm_kind_of(ctx, tid);
|
||||
cg_load_slot(cg, n->mem_load.ptr, SPL_PTR);
|
||||
cg_operand(cg, n->mem_load.ptr, SPL_PTR, 0);
|
||||
CG_LOAD(cg, k);
|
||||
cg_store_slot(cg, ref, k);
|
||||
cg_result(cg, ref, k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -585,8 +826,8 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
ptr_slot(vec_at(cg->frame.slots, n->mem_store.ptr).result_off), tid);
|
||||
} else {
|
||||
uint8_t k = vm_kind_of(ctx, tid);
|
||||
cg_load_slot(cg, n->mem_store.ptr, SPL_PTR);
|
||||
cg_load_slot(cg, n->mem_store.val, k);
|
||||
cg_operand(cg, n->mem_store.ptr, SPL_PTR, 0);
|
||||
cg_operand(cg, n->mem_store.val, k, 1);
|
||||
CG_STORE(cg, k);
|
||||
}
|
||||
break;
|
||||
@@ -596,24 +837,24 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
usize elem_size = ir_type_size(ctx, n->mem_offset.tid);
|
||||
if (elem_size == 0)
|
||||
elem_size = 1;
|
||||
cg_load_slot(cg, n->mem_offset.ptr, SPL_PTR);
|
||||
cg_load_slot(cg, n->mem_offset.offset, SPL_U64);
|
||||
cg_operand(cg, n->mem_offset.ptr, SPL_PTR, 0);
|
||||
cg_operand(cg, n->mem_offset.offset, SPL_U64, 1);
|
||||
CG_PUSH(cg, SPL_U64, elem_size);
|
||||
CG_OP(cg, SPL_MUL, SPL_U64);
|
||||
CG_OP(cg, SPL_ADD, SPL_PTR);
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
cg_result(cg, ref, SPL_PTR);
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_IR_MEM_FIELD_PTR: {
|
||||
spl_type_id_t agg_tid = n->mem_field_ptr.tid;
|
||||
usize off = ir_agg_field_off(ctx, agg_tid, n->mem_field_ptr.field_idx);
|
||||
cg_load_slot(cg, n->mem_field_ptr.agg, SPL_PTR);
|
||||
cg_operand(cg, n->mem_field_ptr.agg, SPL_PTR, 0);
|
||||
if (off) {
|
||||
CG_PUSH(cg, SPL_U64, off);
|
||||
CG_OP(cg, SPL_ADD, SPL_PTR);
|
||||
}
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
cg_result(cg, ref, SPL_PTR);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -742,7 +983,7 @@ static void cg_typeop(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
return;
|
||||
}
|
||||
CG_PUSH(cg, SPL_U64, v);
|
||||
cg_store_slot(cg, ref, SPL_U64);
|
||||
cg_result(cg, ref, SPL_U64);
|
||||
}
|
||||
|
||||
static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
@@ -829,44 +1070,47 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref);
|
||||
spl_type_id_t ptid = ir_result_tid(ctx, pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
cg_operand(cg, pref, pk, i);
|
||||
}
|
||||
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 一个结果 */
|
||||
emit(cg, SPL_DROP, SPL_VOID, 0); /* NCALL always push result */
|
||||
else
|
||||
cg_store_slot(cg, ref, rk);
|
||||
cg_result(cg, ref, rk);
|
||||
} else {
|
||||
spl_type_id_t ret_t = n->control_call.tid;
|
||||
bool ret_is_sret = ir_is_aggregate(ctx, ret_t);
|
||||
usize sret_off = 0;
|
||||
usize j = 0;
|
||||
|
||||
if (ret_is_sret) {
|
||||
sret_off = vec_at(cg->frame.slots, ref).data_off;
|
||||
CG_LADDR(cg, sret_off);
|
||||
j = 1;
|
||||
}
|
||||
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(ctx, pn);
|
||||
uint8_t pk = vm_kind_of(ctx, ptid);
|
||||
cg_load_slot(cg, pref, pk);
|
||||
cg_operand(cg, pref, pk, j);
|
||||
j++;
|
||||
}
|
||||
cg_load_slot(cg, fref, SPL_PTR);
|
||||
cg_operand(cg, fref, SPL_PTR, j);
|
||||
spl_vm_val_t actual_nargs = nargs + (ret_is_sret ? 1 : 0);
|
||||
emit(cg, SPL_CALL, SPL_VOID, actual_nargs);
|
||||
|
||||
if (ret_is_sret) {
|
||||
/* 结果槽保存 sret 指针,后续 agg_extract 把它当聚合首地址 */
|
||||
/* result slot saves sret pointer */
|
||||
CG_LADDR(cg, sret_off);
|
||||
cg_store_slot(cg, ref, SPL_PTR);
|
||||
cg_result(cg, ref, SPL_PTR);
|
||||
} else {
|
||||
uint8_t rk = vm_kind_of(ctx, ret_t);
|
||||
if (rk != SPL_VOID)
|
||||
cg_store_slot(cg, ref, rk);
|
||||
cg_result(cg, ref, rk);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -933,10 +1177,10 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
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_operand(cg, n->arith.left, SPL_BOOL, 0);
|
||||
CG_PUSH(cg, SPL_BOOL, 0);
|
||||
CG_OP(cg, SPL_EQ, SPL_BOOL);
|
||||
cg_store_slot(cg, ref, SPL_BOOL);
|
||||
cg_result(cg, ref, SPL_BOOL);
|
||||
} else {
|
||||
cg_unop(cg, ref, n, SPL_NOT);
|
||||
}
|
||||
@@ -1098,9 +1342,49 @@ static usize translate_function(spl_ir2vm_t *ctx, spl_ir_func_ref_t fid, fix_vec
|
||||
for (usize i = 0; i < nnodes; ++i)
|
||||
vec_push(cg.node_ip, 0);
|
||||
|
||||
unsigned char *leader = NULL;
|
||||
cg.opt = ctx->opt;
|
||||
if (ctx->opt) {
|
||||
cg.stk_loc = (uint8_t *)calloc(nnodes, 1);
|
||||
cg.stk_pos = (usize *)calloc(nnodes, sizeof(usize));
|
||||
cg.use_left = (usize *)calloc(nnodes, sizeof(usize));
|
||||
cg.at_pos = (usize *)calloc(nnodes, sizeof(usize));
|
||||
leader = (unsigned char *)calloc(nnodes, 1);
|
||||
cg.tracked = 0;
|
||||
for (usize i = 1; i < nnodes; ++i)
|
||||
count_refs(&cg, &vec_at(irf->nodes, i));
|
||||
if (nnodes > 1)
|
||||
leader[1] = 1;
|
||||
for (usize i = 1; i < nnodes; ++i) {
|
||||
const spl_ir_node_t *n = &vec_at(irf->nodes, i);
|
||||
if (n->kind == SPL_IR_CONTROL_BR) {
|
||||
if (n->control_br.true_label < nnodes)
|
||||
leader[n->control_br.true_label] = 1;
|
||||
if (n->control_br.false_label < nnodes)
|
||||
leader[n->control_br.false_label] = 1;
|
||||
} else if (n->kind == SPL_IR_CONTROL_JMP) {
|
||||
if (n->control_jmp.label < nnodes)
|
||||
leader[n->control_jmp.label] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (usize i = 1; i < nnodes; ++i) {
|
||||
const spl_ir_node_t *n = &vec_at(irf->nodes, i);
|
||||
if (cg.opt) {
|
||||
if (leader[i] || node_needs_slots(&cg, n))
|
||||
cg_flush(&cg);
|
||||
}
|
||||
vec_at(cg.node_ip, i) = ip_of(&cg);
|
||||
cg_node(&cg, i, &vec_at(irf->nodes, i));
|
||||
cg_node(&cg, i, n);
|
||||
}
|
||||
if (cg.opt) {
|
||||
cg_flush(&cg);
|
||||
free(cg.stk_loc);
|
||||
free(cg.stk_pos);
|
||||
free(cg.use_left);
|
||||
free(cg.at_pos);
|
||||
free(leader);
|
||||
}
|
||||
|
||||
for (usize i = 0; i < vec_size(local_fixups); ++i) {
|
||||
@@ -1124,12 +1408,13 @@ 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,
|
||||
spl_layout_t *layout, const spl_attr_t *attr) {
|
||||
spl_layout_t *layout, const spl_attr_t *attr, int opt) {
|
||||
Assert(ir != NULL && type != NULL && attr != NULL);
|
||||
ctx->ir = ir;
|
||||
ctx->type = type;
|
||||
ctx->attr = attr;
|
||||
ctx->layout = layout;
|
||||
ctx->opt = opt;
|
||||
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
|
||||
spl_prog_init(&ctx->prog);
|
||||
|
||||
|
||||
Reference in new issue
Block a user