stage1 实现ir2vm 修复nob test命令的构建问题
This commit is contained in:
1 parent
87d9b7ea34
commit
a64a96f9a4
11 files changed
+1565
-195
No files matched your search
+81
-45
@@ -106,8 +106,8 @@ static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
|
||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->field.obj);
|
||||
if (!slice_val)
|
||||
return 0;
|
||||
return spl_ir_builder_agg_extract(a->ir, usize_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX,
|
||||
slice_val);
|
||||
return spl_ir_builder_agg_extract(a->ir, recv->ir_type_id, usize_ir,
|
||||
SPL_SLICE_LEN_FIELD_IDX, slice_val);
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
@@ -160,12 +160,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
|
||||
if (!spl_type_agg_member_idx(a->sema->type, agg_ir, n->field.field, &idx))
|
||||
return 0;
|
||||
|
||||
spl_type_node_t *agg_n = spl_type_node(a->sema->type, agg_ir);
|
||||
if (!agg_n)
|
||||
return 0;
|
||||
spl_type_id_t field_ir = vec_at(agg_n->agg_type.variants, idx).type_id;
|
||||
|
||||
return spl_ir_builder_mem_field(a->ir, field_ir, base, idx);
|
||||
return spl_ir_builder_mem_field(a->ir, agg_ir, base, idx);
|
||||
}
|
||||
case SPL_AST_EXPR_INDEX: {
|
||||
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->index.obj);
|
||||
@@ -442,16 +437,26 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
spl_ir_node_ref_t fn = emit_expr(a, n->call.callee);
|
||||
if (!fn)
|
||||
return 0;
|
||||
|
||||
/* 先求所有参数 */
|
||||
usize nargs = vec_size(n->call.args);
|
||||
spl_ir_node_ref_vec_t arg_refs;
|
||||
vec_init(arg_refs);
|
||||
for (usize i = 0; i < nargs; ++i)
|
||||
vec_push(arg_refs, emit_expr(a, vec_at(n->call.args, i)));
|
||||
|
||||
/* 再创建 call 节点 */
|
||||
spl_type_id_t ret_t = node_ir(a, n);
|
||||
spl_ir_node_ref_t call = spl_ir_builder_control_call(a->ir, ret_t, fn);
|
||||
if (!call)
|
||||
if (!call) {
|
||||
vec_free(arg_refs);
|
||||
return 0;
|
||||
for (usize i = 0; i < vec_size(n->call.args); ++i) {
|
||||
spl_ir_node_ref_t arg = emit_expr(a, vec_at(n->call.args, i));
|
||||
if (!arg)
|
||||
return 0;
|
||||
spl_ir_builder_control_call_param(a->ir, call, arg);
|
||||
}
|
||||
|
||||
for (usize i = 0; i < vec_size(arg_refs); ++i)
|
||||
spl_ir_builder_control_call_param(a->ir, call, vec_at(arg_refs, i));
|
||||
vec_free(arg_refs);
|
||||
|
||||
return call;
|
||||
}
|
||||
case SPL_AST_EXPR_FIELD: {
|
||||
@@ -478,15 +483,25 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
return emit_cast(a, n);
|
||||
case SPL_AST_EXPR_TUPLE: {
|
||||
spl_type_id_t t = node_ir(a, n);
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
||||
if (!node)
|
||||
return 0;
|
||||
for (usize i = 0; i < vec_size(n->tuple.elems); ++i) {
|
||||
usize nelems = vec_size(n->tuple.elems);
|
||||
|
||||
spl_ir_node_ref_vec_t field_refs;
|
||||
vec_init(field_refs);
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
spl_ir_node_ref_t f = emit_expr(a, vec_at(n->tuple.elems, i));
|
||||
if (!f)
|
||||
return 0;
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||
Panic("tuple element emit failed");
|
||||
vec_push(field_refs, f);
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
||||
if (!node)
|
||||
Panic("agg_construct failed for tuple");
|
||||
|
||||
for (usize i = 0; i < nelems; ++i)
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, vec_at(field_refs, i));
|
||||
|
||||
vec_free(field_refs);
|
||||
return node;
|
||||
}
|
||||
case SPL_AST_EXPR_ARRAY_LIT: {
|
||||
@@ -494,16 +509,25 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
if (!t)
|
||||
Panic("array literal has no type after sema");
|
||||
|
||||
usize nelems = vec_size(n->array_literal.elems);
|
||||
|
||||
spl_ir_node_ref_vec_t field_refs;
|
||||
vec_init(field_refs);
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
spl_ir_node_ref_t f = emit_expr(a, vec_at(n->array_literal.elems, i));
|
||||
if (!f)
|
||||
Panic("array element emit failed");
|
||||
vec_push(field_refs, f);
|
||||
}
|
||||
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t);
|
||||
if (!node)
|
||||
Panic("agg_construct failed for array literal");
|
||||
|
||||
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) {
|
||||
spl_ir_node_ref_t f = emit_expr(a, vec_at(n->array_literal.elems, i));
|
||||
if (!f)
|
||||
Panic("array element emit failed");
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, f);
|
||||
}
|
||||
for (usize i = 0; i < nelems; ++i)
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, vec_at(field_refs, i));
|
||||
|
||||
vec_free(field_refs);
|
||||
return node;
|
||||
}
|
||||
case SPL_AST_EXPR_AGGREGATE_LIT: {
|
||||
@@ -575,41 +599,53 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
|
||||
if (!obj_ln)
|
||||
return 0;
|
||||
|
||||
/* 目前只处理数组->切片的完整形式 arr[..](无 begin / end)
|
||||
或 arr[begin..end] 的通用形式。简化实现只做完整切片。 */
|
||||
spl_type_id_t slice_ir = node_ir(a, n); /* struct{ptr, len} */
|
||||
spl_type_id_t slice_ir = node_ir(a, n);
|
||||
if (!slice_ir)
|
||||
return 0;
|
||||
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir);
|
||||
if (!node)
|
||||
return 0;
|
||||
spl_lang_type_id_t elem_lang = obj_ln->extra.elem;
|
||||
spl_type_id_t elem_ir = to_ir_type(a, elem_lang);
|
||||
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
|
||||
|
||||
/* 取数组元素指针 */
|
||||
spl_ir_node_ref_t base = emit_lvalue(a, n->slice.obj);
|
||||
if (!base)
|
||||
return 0;
|
||||
|
||||
spl_type_id_t ptr_ir =
|
||||
spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_ln->extra.elem));
|
||||
spl_ir_node_ref_t begin_v = 0;
|
||||
if (n->slice.begin)
|
||||
begin_v = emit_expr(a, n->slice.begin);
|
||||
else
|
||||
begin_v = spl_ir_builder_type_const_int(a->ir, usize_ir, 0);
|
||||
if (!begin_v)
|
||||
return 0;
|
||||
|
||||
/* 字段 0:ptr */
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, base);
|
||||
spl_ir_node_ref_t ptr = spl_ir_builder_mem_offset(a->ir, elem_ir, base, begin_v);
|
||||
if (!ptr)
|
||||
return 0;
|
||||
|
||||
/* 字段 1:len —— 数组取 len,切片取原切片 len */
|
||||
spl_ir_node_ref_t len = 0;
|
||||
if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
||||
spl_ir_node_ref_t end_v = 0;
|
||||
if (n->slice.end) {
|
||||
end_v = emit_expr(a, n->slice.end);
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) {
|
||||
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id);
|
||||
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
len = spl_ir_builder_type_const_int(a->ir, to_ir_type(a, usize), arr->array_type.len);
|
||||
end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
|
||||
} else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) {
|
||||
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
|
||||
spl_lang_type_id_t usize = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
|
||||
len = spl_ir_builder_agg_extract(a->ir, to_ir_type(a, usize), to_ir_type(a, usize),
|
||||
SPL_SLICE_LEN_FIELD_IDX, slice_val);
|
||||
end_v = spl_ir_builder_agg_extract(a->ir, obj_ln->ir_type_id, usize_ir,
|
||||
SPL_SLICE_LEN_FIELD_IDX, slice_val);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if (!end_v)
|
||||
return 0;
|
||||
|
||||
spl_ir_node_ref_t len = spl_ir_builder_arith_sub(a->ir, usize_ir, end_v, begin_v);
|
||||
|
||||
spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir);
|
||||
if (!node)
|
||||
return 0;
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, ptr);
|
||||
spl_ir_builder_agg_construct_field(a->ir, node, len);
|
||||
return node;
|
||||
}
|
||||
|
||||
+4
-3
@@ -196,8 +196,8 @@ static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) {
|
||||
printf(" float=%f", n->type_const.float_lit);
|
||||
} else if (t && t->kind == SPL_TYPE_FN) {
|
||||
printf(" fn#%zu", n->type_const.fn);
|
||||
} else if (t && t->kind == SPL_TYPE_PTR) {
|
||||
printf(" str=\"%s\"", n->type_const.cstr_lit ? n->type_const.cstr_lit : "?");
|
||||
// } else if (t && t->kind == SPL_TYPE_PTR) {
|
||||
// printf(" str=\"%s\"", n->type_const.cstr_lit ? n->type_const.cstr_lit : "?");
|
||||
} else if (t && t->kind == SPL_TYPE_INT && t->int_type.bits == 8) {
|
||||
printf(" char='%c'", n->type_const.ch_lit);
|
||||
} else {
|
||||
@@ -592,7 +592,8 @@ spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_i
|
||||
spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST);
|
||||
spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref);
|
||||
n->type_const.tid = tid;
|
||||
n->type_const.cstr_lit = val;
|
||||
TODO();
|
||||
// n->type_const.cstr_lit = val;
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -145,7 +145,7 @@ typedef struct {
|
||||
void *ptr_lit;
|
||||
usize int_lit;
|
||||
double float_lit;
|
||||
const char *cstr_lit;
|
||||
// const char *cstr_lit;
|
||||
char ch_lit;
|
||||
spl_ir_func_ref_t fn;
|
||||
};
|
||||
|
||||
+994
-54
File diff suppressed because it is too large.
Load diff
@@ -24,6 +24,7 @@ typedef struct {
|
||||
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type);
|
||||
void spl_ir2vm_drop(spl_ir2vm_t *ctx);
|
||||
|
||||
int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref);
|
||||
int spl_ir2vm_run(spl_ir2vm_t *ctx);
|
||||
void spl_ir2vm_dump(spl_ir2vm_t *ctx);
|
||||
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
#include "spl_layout.h"
|
||||
|
||||
static void infos_grow(spl_layout_t *layout, usize n) {
|
||||
while (vec_size(layout->infos) < n) {
|
||||
spl_layout_info_t info = {0};
|
||||
vec_init(info.field_bit_offsets);
|
||||
vec_init(info.field_bit_sizes);
|
||||
vec_push(layout->infos, info);
|
||||
}
|
||||
}
|
||||
|
||||
static spl_layout_info_t *infos_at(spl_layout_t *layout, spl_type_id_t id) {
|
||||
if (id == 0 || id >= vec_size(layout->infos))
|
||||
return NULL;
|
||||
return &vec_at(layout->infos, id);
|
||||
}
|
||||
|
||||
void spl_layout_add_scalar(spl_layout_t *layout, usize size, usize abi_align) {
|
||||
spl_layout_scalar_t s = {0};
|
||||
s.size = size;
|
||||
s.abi_align = abi_align;
|
||||
s.pref_align = abi_align;
|
||||
vec_init(s.invalid_values);
|
||||
vec_push(layout->scalars, s);
|
||||
}
|
||||
|
||||
void spl_layout_add_ptr(spl_layout_t *layout, usize addr_space, usize size, usize align) {
|
||||
spl_layout_ptr_t p = {0};
|
||||
p.add_space = addr_space;
|
||||
p.ptr_size = size;
|
||||
p.ptr_align = align;
|
||||
vec_push(layout->pointers, p);
|
||||
}
|
||||
|
||||
void spl_layout_init(spl_layout_t *layout, spl_layout_target_t *target) {
|
||||
vec_init(layout->scalars);
|
||||
vec_init(layout->pointers);
|
||||
vec_init(layout->infos);
|
||||
layout->target = target;
|
||||
|
||||
/* 默认聚合策略:按最大字段对齐,不允许重排 */
|
||||
layout->aggregate.allow_field_reordering = false;
|
||||
layout->aggregate.align_rule = ALIGN_MAX;
|
||||
layout->aggregate.fixed_align = 0;
|
||||
|
||||
/* 常见 64 位平台的默认布局。
|
||||
若目标平台不适用,调用者 clear 后自行 add_*。 */
|
||||
spl_layout_add_scalar(layout, 1, 1); /* i8 / u8 / bool */
|
||||
spl_layout_add_scalar(layout, 2, 2); /* i16 / u16 */
|
||||
spl_layout_add_scalar(layout, 4, 4); /* i32 / u32 / f32 */
|
||||
spl_layout_add_scalar(layout, 8, 8); /* i64 / u64 / f64 */
|
||||
|
||||
usize ps = sizeof(void *);
|
||||
spl_layout_add_ptr(layout, 0, ps, ps);
|
||||
}
|
||||
|
||||
void spl_layout_drop(spl_layout_t *layout) {
|
||||
for (usize i = 0; i < vec_size(layout->scalars); ++i)
|
||||
vec_free(vec_at(layout->scalars, i).invalid_values);
|
||||
vec_free(layout->scalars);
|
||||
|
||||
vec_free(layout->pointers);
|
||||
|
||||
for (usize i = 0; i < vec_size(layout->infos); ++i) {
|
||||
vec_free(vec_at(layout->infos, i).field_bit_offsets);
|
||||
vec_free(vec_at(layout->infos, i).field_bit_sizes);
|
||||
}
|
||||
vec_free(layout->infos);
|
||||
}
|
||||
|
||||
static const spl_layout_scalar_t *scalar_for_size(spl_layout_t *layout, usize size_bytes) {
|
||||
for (usize i = 0; i < vec_size(layout->scalars); ++i) {
|
||||
spl_layout_scalar_t *s = &vec_at(layout->scalars, i);
|
||||
if (s->size == size_bytes)
|
||||
return s;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const spl_layout_ptr_t *default_ptr(spl_layout_t *layout) {
|
||||
if (vec_size(layout->pointers) == 0)
|
||||
return NULL;
|
||||
return &vec_at(layout->pointers, 0);
|
||||
}
|
||||
|
||||
static bool layout_scalar(spl_layout_t *layout, spl_type_node_t *tn, spl_layout_info_t *out) {
|
||||
usize size_bits = 0;
|
||||
switch (tn->kind) {
|
||||
case SPL_TYPE_INT:
|
||||
if (tn->int_type.bits == 0)
|
||||
return false; /* comptime_int 未落地 */
|
||||
size_bits = tn->int_type.bits;
|
||||
break;
|
||||
case SPL_TYPE_FLOAT:
|
||||
if (tn->float_type.bits == 0)
|
||||
return false; /* comptime_float 未落地 */
|
||||
size_bits = tn->float_type.bits;
|
||||
break;
|
||||
case SPL_TYPE_BOOL:
|
||||
size_bits = 8;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
usize size_bytes = (size_bits + 7) / 8;
|
||||
const spl_layout_scalar_t *sl = scalar_for_size(layout, size_bytes);
|
||||
if (!sl)
|
||||
return false;
|
||||
|
||||
out->size_bits = sl->size * 8;
|
||||
out->align_bits = sl->abi_align * 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool layout_ptr(spl_layout_t *layout, spl_layout_info_t *out) {
|
||||
const spl_layout_ptr_t *pl = default_ptr(layout);
|
||||
if (!pl)
|
||||
return false;
|
||||
out->size_bits = pl->ptr_size * 8;
|
||||
out->align_bits = pl->ptr_align * 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
static usize round_up_bits(usize x, usize align_bits) {
|
||||
if (align_bits <= 1)
|
||||
return x;
|
||||
usize a = align_bits;
|
||||
return (x + a - 1) / a * a;
|
||||
}
|
||||
|
||||
static bool layout_agg(spl_layout_t *layout, spl_type_node_t *tn, spl_layout_info_t *out) {
|
||||
usize n = vec_size(tn->agg_type.variants);
|
||||
if (n == 0) {
|
||||
out->size_bits = 0;
|
||||
out->align_bits = 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
usize max_align_bits = 8;
|
||||
usize offset_bits = 0;
|
||||
bool is_union = (tn->kind == SPL_TYPE_UNION);
|
||||
|
||||
for (usize i = 0; i < n; ++i) {
|
||||
spl_type_member_t *m = &vec_at(tn->agg_type.variants, i);
|
||||
spl_layout_info_t *fi = infos_at(layout, m->type_id);
|
||||
if (!fi || !fi->resolved)
|
||||
return false;
|
||||
|
||||
usize field_align_bits = fi->align_bits ? fi->align_bits : 8;
|
||||
|
||||
if (is_union) {
|
||||
vec_push(out->field_bit_offsets, 0);
|
||||
vec_push(out->field_bit_sizes, fi->size_bits);
|
||||
if (fi->size_bits > out->size_bits)
|
||||
out->size_bits = fi->size_bits;
|
||||
} else {
|
||||
offset_bits = round_up_bits(offset_bits, field_align_bits);
|
||||
vec_push(out->field_bit_offsets, offset_bits);
|
||||
vec_push(out->field_bit_sizes, fi->size_bits);
|
||||
offset_bits += fi->size_bits;
|
||||
}
|
||||
if (field_align_bits > max_align_bits)
|
||||
max_align_bits = field_align_bits;
|
||||
}
|
||||
|
||||
/* 聚合对齐策略 */
|
||||
usize final_align_bits = max_align_bits;
|
||||
if (layout->aggregate.align_rule == ALIGN_FIXED) {
|
||||
final_align_bits = layout->aggregate.fixed_align * 8;
|
||||
} else if (layout->aggregate.align_rule == ALIGN_MAX_WITH_MIN) {
|
||||
usize min_bits = layout->aggregate.fixed_align * 8;
|
||||
if (final_align_bits < min_bits)
|
||||
final_align_bits = min_bits;
|
||||
}
|
||||
|
||||
if (is_union)
|
||||
out->size_bits = round_up_bits(out->size_bits, final_align_bits);
|
||||
else
|
||||
out->size_bits = round_up_bits(offset_bits, final_align_bits);
|
||||
out->align_bits = final_align_bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void resolve_type(spl_layout_t *layout, spl_type_t *type, spl_type_id_t id) {
|
||||
spl_layout_info_t *info = infos_at(layout, id);
|
||||
if (!info || info->resolved)
|
||||
return;
|
||||
|
||||
spl_type_node_t *tn = spl_type_node(type, id);
|
||||
if (!tn)
|
||||
return;
|
||||
|
||||
/* 先标记已解析:自引用类型(通过 ptr)不会无限递归,
|
||||
但保持防御性写法。 */
|
||||
info->resolved = true;
|
||||
|
||||
switch (tn->kind) {
|
||||
case SPL_TYPE_ERROR:
|
||||
case SPL_TYPE_INFER:
|
||||
case SPL_TYPE_FORALL:
|
||||
case SPL_TYPE_EXISTS:
|
||||
case SPL_TYPE_NEVER:
|
||||
case SPL_TYPE_UNIT:
|
||||
info->size_bits = 0;
|
||||
info->align_bits = 8;
|
||||
return;
|
||||
|
||||
case SPL_TYPE_ANY:
|
||||
/* 顶层类型:stage1 按不透明指针处理 */
|
||||
layout_ptr(layout, info);
|
||||
return;
|
||||
|
||||
case SPL_TYPE_BOOL:
|
||||
case SPL_TYPE_INT:
|
||||
case SPL_TYPE_FLOAT:
|
||||
layout_scalar(layout, tn, info);
|
||||
return;
|
||||
|
||||
case SPL_TYPE_PTR:
|
||||
layout_ptr(layout, info);
|
||||
return;
|
||||
|
||||
case SPL_TYPE_ARRAY: {
|
||||
resolve_type(layout, type, tn->array_type.element);
|
||||
spl_layout_info_t *elem = infos_at(layout, tn->array_type.element);
|
||||
if (!elem || !elem->resolved)
|
||||
return;
|
||||
info->size_bits = elem->size_bits * tn->array_type.len;
|
||||
info->align_bits = elem->align_bits;
|
||||
return;
|
||||
}
|
||||
|
||||
case SPL_TYPE_STRUCT:
|
||||
case SPL_TYPE_UNION:
|
||||
case SPL_TYPE_ENUM:
|
||||
case SPL_TYPE_SHAPE: {
|
||||
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) {
|
||||
spl_type_member_t *m = &vec_at(tn->agg_type.variants, i);
|
||||
resolve_type(layout, type, m->type_id);
|
||||
}
|
||||
layout_agg(layout, tn, info);
|
||||
return;
|
||||
}
|
||||
|
||||
case SPL_TYPE_FN:
|
||||
/* 函数类型按函数指针布局 */
|
||||
for (usize i = 0; i < vec_size(tn->fn_type.params); ++i)
|
||||
resolve_type(layout, type, vec_at(tn->fn_type.params, i));
|
||||
resolve_type(layout, type, tn->fn_type.ret);
|
||||
layout_ptr(layout, info);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void spl_layout_resolve(spl_layout_t *layout, spl_type_t *type) {
|
||||
infos_grow(layout, vec_size(type->type_table));
|
||||
for (usize i = 1; i < vec_size(type->type_table); ++i)
|
||||
resolve_type(layout, type, i);
|
||||
}
|
||||
|
||||
const spl_layout_info_t *spl_layout_info_of(spl_layout_t *layout, spl_type_id_t id) {
|
||||
spl_layout_info_t *info = infos_at(layout, id);
|
||||
if (!info || !info->resolved)
|
||||
return NULL;
|
||||
return info;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef __SPL_LAYOUT_H__
|
||||
#define __SPL_LAYOUT_H__
|
||||
|
||||
#include "spl_type.h"
|
||||
|
||||
typedef struct {
|
||||
usize size;
|
||||
usize abi_align;
|
||||
usize pref_align;
|
||||
VEC(usize) invalid_values;
|
||||
} spl_layout_scalar_t;
|
||||
|
||||
typedef struct {
|
||||
usize add_space;
|
||||
usize ptr_size;
|
||||
usize ptr_align;
|
||||
} spl_layout_ptr_t;
|
||||
|
||||
typedef struct {
|
||||
bool allow_field_reordering;
|
||||
enum { ALIGN_MAX, ALIGN_FIXED, ALIGN_MAX_WITH_MIN } align_rule;
|
||||
usize fixed_align;
|
||||
} spl_layout_agg_t;
|
||||
|
||||
typedef struct {
|
||||
usize size_bits;
|
||||
usize align_bits;
|
||||
VEC(usize) field_bit_offsets;
|
||||
VEC(usize) field_bit_sizes;
|
||||
bool resolved;
|
||||
} spl_layout_info_t;
|
||||
|
||||
typedef struct {
|
||||
enum { SPL_BIG_ENDIAN, SPL_LITTLE_ENDIAN } endian; // TODO 更多位存储方式
|
||||
|
||||
} spl_layout_target_t;
|
||||
|
||||
typedef struct {
|
||||
VEC(spl_layout_scalar_t) scalars;
|
||||
VEC(spl_layout_ptr_t) pointers;
|
||||
spl_layout_agg_t aggregate;
|
||||
VEC(spl_layout_info_t) infos;
|
||||
spl_layout_target_t *target;
|
||||
} spl_layout_t;
|
||||
|
||||
void spl_layout_init(spl_layout_t *layout, spl_layout_target_t *target);
|
||||
void spl_layout_drop(spl_layout_t *layout);
|
||||
|
||||
void spl_layout_resolve(spl_layout_t *layout, spl_type_t *type);
|
||||
|
||||
void spl_layout_add_scalar(spl_layout_t *layout, usize size, usize abi_align);
|
||||
void spl_layout_add_ptr(spl_layout_t *layout, usize addr_space, usize size, usize align);
|
||||
|
||||
const spl_layout_info_t *spl_layout_info_of(spl_layout_t *layout, spl_type_id_t id);
|
||||
|
||||
#endif /* __SPL_LAYOUT_H__ */
|
||||
+26
-49
@@ -309,58 +309,31 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
return bt;
|
||||
}
|
||||
|
||||
/* 比较:数值类型允许异构比较;其他走 balance */
|
||||
if (op == SPL_OP_CMP_EQ || op == SPL_OP_CMP_NE || op == SPL_OP_CMP_LT ||
|
||||
op == SPL_OP_CMP_LE || op == SPL_OP_CMP_GT || op == SPL_OP_CMP_GE) {
|
||||
|
||||
/* 比较:结果 bool,节点存操作数类型;不依赖 expected */
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
if (!lt || !rt)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||
bool l_num = ln && (ln->kind == SPL_LANG_TYPE_INT || ln->kind == SPL_LANG_TYPE_FLOAT);
|
||||
bool r_num = rn && (rn->kind == SPL_LANG_TYPE_INT || rn->kind == SPL_LANG_TYPE_FLOAT);
|
||||
|
||||
if (l_num && r_num) {
|
||||
/* 数值比较:允许异构。仅当一侧 comptime 时把另一侧具体类型下推 */
|
||||
if (ln->kind == SPL_LANG_TYPE_INT && rn->kind == SPL_LANG_TYPE_INT) {
|
||||
spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id);
|
||||
spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (lir && lir->int_type.bits == 0)
|
||||
sema_check(sema, n->binary.left, rt);
|
||||
else if (rir && rir->int_type.bits == 0)
|
||||
sema_check(sema, n->binary.right, lt);
|
||||
} else if (ln->kind == SPL_LANG_TYPE_FLOAT && rn->kind == SPL_LANG_TYPE_FLOAT) {
|
||||
spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id);
|
||||
spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (lir && lir->float_type.bits == 0)
|
||||
sema_check(sema, n->binary.left, rt);
|
||||
else if (rir && rir->float_type.bits == 0)
|
||||
sema_check(sema, n->binary.right, lt);
|
||||
}
|
||||
} else {
|
||||
/* 非数值:要求 coerce 到共同类型 */
|
||||
spl_lang_type_id_t common =
|
||||
(lt == rt) ? lt : spl_lang_type_balance(sema->type, lt, rt);
|
||||
if (!common) {
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
if (!sema_check(sema, n->binary.left, common))
|
||||
return 0;
|
||||
if (!sema_check(sema, n->binary.right, common))
|
||||
return 0;
|
||||
spl_lang_type_id_t common = 0;
|
||||
if (lt == rt)
|
||||
common = lt;
|
||||
else
|
||||
common = spl_lang_type_balance(sema->type, lt, rt);
|
||||
if (!common) {
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
n->resolved_lang_tid = bt;
|
||||
n->expected_lang_tid = 0;
|
||||
return bt;
|
||||
}
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
|
||||
n->resolved_lang_tid = common;
|
||||
return spl_lang_make_bool(sema->type);
|
||||
}
|
||||
/* 算术 / 位 / 移位:两侧 check 到 expected */
|
||||
if (!sema_check(sema, n->binary.left, expected))
|
||||
return 0;
|
||||
@@ -665,25 +638,29 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return bt;
|
||||
}
|
||||
|
||||
/* 比较 */
|
||||
if (op == SPL_OP_CMP_EQ || op == SPL_OP_CMP_NE || op == SPL_OP_CMP_LT ||
|
||||
op == SPL_OP_CMP_LE || op == SPL_OP_CMP_GT || op == SPL_OP_CMP_GE) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
if (!lt || !rt)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_id_t common = 0;
|
||||
if (lt == rt)
|
||||
common = lt;
|
||||
else
|
||||
common = spl_lang_type_balance(sema->type, lt, rt);
|
||||
if (common) {
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
if (!common) {
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
n->resolved_lang_tid = bt;
|
||||
return bt;
|
||||
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
|
||||
n->resolved_lang_tid = common;
|
||||
return spl_lang_make_bool(sema->type);
|
||||
}
|
||||
|
||||
/* Range */
|
||||
|
||||
+17
-17
@@ -129,25 +129,25 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// spl_ir2vm_t ir2vm;
|
||||
// spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type);
|
||||
// int rc = spl_ir2vm_run(&ir2vm);
|
||||
// if (rc != 0) {
|
||||
// printf("ir2vm error %d", rc);
|
||||
// return rc;
|
||||
// }
|
||||
// if (dump == DUMP_VM) {
|
||||
// spl_prog_dump(&ir2vm.prog);
|
||||
// // memory leak
|
||||
// return 0;
|
||||
// }
|
||||
spl_ir2vm_t ir2vm;
|
||||
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type);
|
||||
int rc = spl_ir2vm_run(&ir2vm);
|
||||
if (rc != 0) {
|
||||
printf("ir2vm error %d", rc);
|
||||
return rc;
|
||||
}
|
||||
if (dump == DUMP_VM) {
|
||||
spl_prog_dump(&ir2vm.prog);
|
||||
// memory leak
|
||||
return 0;
|
||||
}
|
||||
|
||||
// spl_prog_store_to_file(outpath, &ir2vm.prog);
|
||||
spl_prog_store_to_file(outpath, &ir2vm.prog);
|
||||
|
||||
// spl_ir2vm_drop(&ir2vm);
|
||||
// spl_ast2ir_drop(&a2ir);
|
||||
// spl_sema_drop(&sema);
|
||||
// spl_ast_drop(&ast);
|
||||
spl_ir2vm_drop(&ir2vm);
|
||||
spl_ast2ir_drop(&a2ir);
|
||||
spl_sema_drop(&sema);
|
||||
spl_ast_drop(&ast);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user