stage2 更多底层函数 stage1 layout正确使用 内置函数重新编写
This commit is contained in:
1 parent
fb0ff9b663
commit
4141e7d574
15 files changed
+2588
-122
No files matched your search
+47
-11
@@ -373,6 +373,40 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
|
||||
spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
|
||||
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
|
||||
}
|
||||
case SPL_INTRIN_ENUM2INT: {
|
||||
/* enum 值 -> 其 tag(判别值);field 0 即 tag。 */
|
||||
spl_ast_node_t *src = spl_ast_node(a->ast, vec_at(*args, 0));
|
||||
spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0));
|
||||
if (!v)
|
||||
return 0;
|
||||
spl_type_id_t agg_t = node_ir(a, src);
|
||||
spl_type_id_t tag_t = node_ir(a, n);
|
||||
if (!agg_t || !tag_t)
|
||||
return 0;
|
||||
return spl_ir_builder_agg_extract(a->ir, agg_t, tag_t, 0, v);
|
||||
}
|
||||
case SPL_INTRIN_FIELD_COUNT: {
|
||||
spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
|
||||
return spl_ir_builder_type_field_count(a->ir, node_ir(a, arg));
|
||||
}
|
||||
case SPL_INTRIN_OFFSETOF: {
|
||||
spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
|
||||
spl_type_id_t agg_t = node_ir(a, arg);
|
||||
if (!agg_t)
|
||||
return 0;
|
||||
spl_ast_node_t *fnode = spl_ast_node(a->ast, vec_at(*args, 1));
|
||||
usize idx = 0;
|
||||
if (fnode && fnode->kind == SPL_AST_EXPR_INT_LIT) {
|
||||
idx = (usize)fnode->int_lit.bits;
|
||||
} else if (fnode && fnode->kind == SPL_AST_EXPR_IDENT) {
|
||||
if (!spl_type_agg_member_idx(&a->sema->type->ir, agg_t, fnode->ident.name, &idx))
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
spl_ir_node_ref_t idx_node = const_usize(a, idx);
|
||||
return spl_ir_builder_type_offsetof(a->ir, agg_t, idx_node);
|
||||
}
|
||||
case SPL_INTRIN_ASSERT: {
|
||||
spl_ir_node_ref_t cond = emit_expr(a, vec_at(*args, 0));
|
||||
if (!cond)
|
||||
@@ -420,11 +454,11 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
|
||||
case SPL_INTRIN_TRUNCATE:
|
||||
case SPL_INTRIN_BIT_CAST:
|
||||
case SPL_INTRIN_FLOAT_CAST:
|
||||
case SPL_INTRIN_INT_FROM_FLOAT:
|
||||
case SPL_INTRIN_FLOAT_FROM_INT:
|
||||
case SPL_INTRIN_INT_FROM_BOOL:
|
||||
case SPL_INTRIN_INT_FROM_PTR:
|
||||
case SPL_INTRIN_PTR_FROM_INT:
|
||||
case SPL_INTRIN_FLOAT2INT:
|
||||
case SPL_INTRIN_INT2FLOAT:
|
||||
case SPL_INTRIN_BOOL2INT:
|
||||
case SPL_INTRIN_PTR2INT:
|
||||
case SPL_INTRIN_INT2PTR:
|
||||
case SPL_INTRIN_PTR_CAST:
|
||||
return ast2ir_intrin_cast(a, n, in, args);
|
||||
case SPL_INTRIN_BREAKPOINT:
|
||||
@@ -619,15 +653,15 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_
|
||||
return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v);
|
||||
return spl_ir_builder_cast_fext(a->ir, ft, tt, v);
|
||||
}
|
||||
case SPL_INTRIN_INT_FROM_FLOAT:
|
||||
case SPL_INTRIN_FLOAT2INT:
|
||||
return spl_ir_builder_case_float2int(a->ir, ft, tt, v);
|
||||
case SPL_INTRIN_FLOAT_FROM_INT:
|
||||
case SPL_INTRIN_INT2FLOAT:
|
||||
return spl_ir_builder_case_int2float(a->ir, ft, tt, v);
|
||||
case SPL_INTRIN_INT_FROM_BOOL:
|
||||
case SPL_INTRIN_BOOL2INT:
|
||||
return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v);
|
||||
case SPL_INTRIN_INT_FROM_PTR:
|
||||
case SPL_INTRIN_PTR2INT:
|
||||
return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v);
|
||||
case SPL_INTRIN_PTR_FROM_INT:
|
||||
case SPL_INTRIN_INT2PTR:
|
||||
return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v);
|
||||
case SPL_INTRIN_PTR_CAST:
|
||||
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
|
||||
@@ -1935,10 +1969,12 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
|
||||
static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); }
|
||||
static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
|
||||
|
||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) {
|
||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, spl_layout_t *layout,
|
||||
const spl_sema_t *sema) {
|
||||
ast2ir->sema = sema;
|
||||
ast2ir->ir = ir;
|
||||
ast2ir->ast = sema->ast;
|
||||
ast2ir->layout = layout;
|
||||
map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp);
|
||||
vec_init(ast2ir->loop_stack);
|
||||
vec_init(ast2ir->defer_stack);
|
||||
|
||||
+3
-1
@@ -23,6 +23,7 @@ typedef struct {
|
||||
const spl_sema_t *sema;
|
||||
spl_ir_builder_t *ir;
|
||||
spl_ast_t *ast;
|
||||
spl_layout_t *layout; /* 借用 splc0 的 layout */
|
||||
spl_def2ir_map_t def2ir_map;
|
||||
spl_loop_ctx_vec_t loop_stack;
|
||||
spl_defer_stack_t defer_stack;
|
||||
@@ -32,7 +33,8 @@ typedef struct {
|
||||
spl_diag_t *diag;
|
||||
} spl_ast2ir_t;
|
||||
|
||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema);
|
||||
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, spl_layout_t *layout,
|
||||
const spl_sema_t *sema);
|
||||
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir);
|
||||
|
||||
void spl_ast2ir_run(spl_ast2ir_t *ast2ir, spl_ast_ptr_vec_t ast_vec);
|
||||
|
||||
+21
-14
@@ -22,18 +22,24 @@ static const spl_intrin_info_t g_intrin_table[] = {
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_FLOAT_CAST] = {"@float_cast", SPL_INTRIN_FLOAT_CAST, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_INT_FROM_FLOAT] = {"@int_from_float", SPL_INTRIN_INT_FROM_FLOAT,
|
||||
SPL_INTRIN_FORM_CALL, 2, 2, SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_FLOAT_FROM_INT] = {"@float_from_int", SPL_INTRIN_FLOAT_FROM_INT,
|
||||
SPL_INTRIN_FORM_CALL, 2, 2, SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_INT_FROM_BOOL] = {"@int_from_bool", SPL_INTRIN_INT_FROM_BOOL, SPL_INTRIN_FORM_CALL,
|
||||
1, 2, SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_INT_FROM_PTR] = {"@int_from_ptr", SPL_INTRIN_INT_FROM_PTR, SPL_INTRIN_FORM_CALL, 1,
|
||||
2, SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_PTR_FROM_INT] = {"@ptr_from_int", SPL_INTRIN_PTR_FROM_INT, SPL_INTRIN_FORM_CALL, 2,
|
||||
2, SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_FLOAT2INT] = {"@float2int", SPL_INTRIN_FLOAT2INT, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_INT2FLOAT] = {"@int2float", SPL_INTRIN_INT2FLOAT, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_BOOL2INT] = {"@bool2int", SPL_INTRIN_BOOL2INT, SPL_INTRIN_FORM_CALL, 1, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_PTR2INT] = {"@ptr2int", SPL_INTRIN_PTR2INT, SPL_INTRIN_FORM_CALL, 1, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_INT2PTR] = {"@int2ptr", SPL_INTRIN_INT2PTR, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_PTR_CAST] = {"@ptr_cast", SPL_INTRIN_PTR_CAST, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_UNIT},
|
||||
[SPL_INTRIN_ENUM2INT] = {"@enum2int", SPL_INTRIN_ENUM2INT, SPL_INTRIN_FORM_CALL, 1, 1,
|
||||
SPL_INTRIN_RESULT_USIZE},
|
||||
[SPL_INTRIN_OFFSETOF] = {"@offsetof", SPL_INTRIN_OFFSETOF, SPL_INTRIN_FORM_CALL, 2, 2,
|
||||
SPL_INTRIN_RESULT_USIZE},
|
||||
[SPL_INTRIN_FIELD_COUNT] = {"@field_count", SPL_INTRIN_FIELD_COUNT, SPL_INTRIN_FORM_CALL, 1, 1,
|
||||
SPL_INTRIN_RESULT_USIZE},
|
||||
};
|
||||
|
||||
static const usize g_intrin_count = sizeof(g_intrin_table) / sizeof(g_intrin_table[0]);
|
||||
@@ -88,14 +94,15 @@ spl_intrin_t spl_intrin_lookup_cast(spl_type_t *type, spl_type_id_t ft, spl_type
|
||||
if (f->kind == SPL_TYPE_FLOAT && t->kind == SPL_TYPE_FLOAT)
|
||||
return SPL_INTRIN_FLOAT_CAST;
|
||||
if (f->kind == SPL_TYPE_BOOL && t->kind == SPL_TYPE_INT)
|
||||
return SPL_INTRIN_INT_FROM_BOOL;
|
||||
return SPL_INTRIN_BOOL2INT;
|
||||
if (f->kind == SPL_TYPE_PTR && t->kind == SPL_TYPE_INT)
|
||||
return SPL_INTRIN_INT_FROM_PTR;
|
||||
return SPL_INTRIN_PTR2INT;
|
||||
if (f->kind == SPL_TYPE_INT && t->kind == SPL_TYPE_PTR)
|
||||
return SPL_INTRIN_PTR_FROM_INT;
|
||||
return SPL_INTRIN_INT2PTR;
|
||||
if (f->kind == SPL_TYPE_PTR && t->kind == SPL_TYPE_PTR)
|
||||
return SPL_INTRIN_PTR_CAST;
|
||||
|
||||
/* int float 刻意不在这里:只能通过显式 builtin 调用。 */
|
||||
/* int float 刻意不在这里:只能通过显式 builtin 调用。
|
||||
enum<->int 也刻意禁止(用 @enum2int 取 tag)。 */
|
||||
return SPL_INTRIN_NONE;
|
||||
}
|
||||
+8
-5
@@ -16,12 +16,15 @@ typedef enum {
|
||||
SPL_INTRIN_TRUNCATE,
|
||||
SPL_INTRIN_BIT_CAST,
|
||||
SPL_INTRIN_FLOAT_CAST,
|
||||
SPL_INTRIN_INT_FROM_FLOAT,
|
||||
SPL_INTRIN_FLOAT_FROM_INT,
|
||||
SPL_INTRIN_INT_FROM_BOOL,
|
||||
SPL_INTRIN_INT_FROM_PTR,
|
||||
SPL_INTRIN_PTR_FROM_INT,
|
||||
SPL_INTRIN_FLOAT2INT,
|
||||
SPL_INTRIN_INT2FLOAT,
|
||||
SPL_INTRIN_BOOL2INT,
|
||||
SPL_INTRIN_PTR2INT,
|
||||
SPL_INTRIN_INT2PTR,
|
||||
SPL_INTRIN_PTR_CAST,
|
||||
SPL_INTRIN_ENUM2INT,
|
||||
SPL_INTRIN_OFFSETOF,
|
||||
SPL_INTRIN_FIELD_COUNT,
|
||||
} spl_intrin_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
+46
-63
@@ -3,49 +3,24 @@
|
||||
|
||||
static usize align_up(usize x, usize a);
|
||||
|
||||
/* size/align/offset 统一取自 layout(spl_layout 是唯一准确来源)。 */
|
||||
static const spl_layout_info_t *ir_layout(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
return spl_layout_info_of(ctx->layout, tid);
|
||||
}
|
||||
|
||||
static usize ir_type_size(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
|
||||
if (!tn)
|
||||
return 8;
|
||||
switch (tn->kind) {
|
||||
case SPL_TYPE_UNIT:
|
||||
const spl_layout_info_t *info = ir_layout(ctx, tid);
|
||||
if (!info)
|
||||
return 0;
|
||||
case SPL_TYPE_BOOL:
|
||||
return (info->size_bits + 7) / 8;
|
||||
}
|
||||
|
||||
static usize ir_type_align(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
const spl_layout_info_t *info = ir_layout(ctx, tid);
|
||||
if (!info)
|
||||
return 1;
|
||||
case SPL_TYPE_INT:
|
||||
return (tn->int_type.bits + 7) / 8;
|
||||
case SPL_TYPE_FLOAT:
|
||||
return (tn->float_type.bits + 7) / 8;
|
||||
case SPL_TYPE_PTR:
|
||||
return sizeof(void *);
|
||||
case SPL_TYPE_FN:
|
||||
return sizeof(void *);
|
||||
case SPL_TYPE_ARRAY:
|
||||
return ir_type_size(ctx, tn->array_type.element) * tn->array_type.len;
|
||||
case SPL_TYPE_ENUM: {
|
||||
usize tag_sz = ir_type_size(ctx, tn->agg_type.tag_type);
|
||||
usize payload_align = 1;
|
||||
usize payload_size = 0;
|
||||
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) {
|
||||
usize vs = ir_type_size(ctx, vec_at(tn->agg_type.variants, i).type_id);
|
||||
if (vs > payload_align)
|
||||
payload_align = vs;
|
||||
if (vs > payload_size)
|
||||
payload_size = vs;
|
||||
}
|
||||
usize payload_off = align_up(tag_sz, payload_align);
|
||||
return align_up(payload_off + payload_size, payload_align);
|
||||
}
|
||||
case SPL_TYPE_STRUCT:
|
||||
case SPL_TYPE_UNION: {
|
||||
usize s = 0;
|
||||
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i)
|
||||
s += ir_type_size(ctx, vec_at(tn->agg_type.variants, i).type_id);
|
||||
return s;
|
||||
}
|
||||
default:
|
||||
return 8;
|
||||
}
|
||||
usize a = info->align_bits / 8;
|
||||
return a ? a : 1;
|
||||
}
|
||||
|
||||
static bool ir_is_aggregate(spl_ir2vm_t *ctx, spl_type_id_t tid) {
|
||||
@@ -98,27 +73,13 @@ static usize ir_agg_field_off(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) {
|
||||
spl_type_node_t *tn = spl_type_node(ctx->type, tid);
|
||||
if (!tn)
|
||||
return 0;
|
||||
if (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_UNION) {
|
||||
usize off = 0;
|
||||
for (usize i = 0; i < idx && i < vec_size(tn->agg_type.variants); ++i)
|
||||
off += ir_type_size(ctx, vec_at(tn->agg_type.variants, i).type_id);
|
||||
return off;
|
||||
}
|
||||
if (tn->kind == SPL_TYPE_ARRAY)
|
||||
return idx * ir_type_size(ctx, tn->array_type.element);
|
||||
if (tn->kind == SPL_TYPE_ENUM) {
|
||||
if (idx == 0)
|
||||
return 0;
|
||||
usize tag_sz = ir_type_size(ctx, tn->agg_type.tag_type);
|
||||
usize payload_align = 1;
|
||||
for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) {
|
||||
usize vs = ir_type_size(ctx, vec_at(tn->agg_type.variants, i).type_id);
|
||||
if (vs > payload_align)
|
||||
payload_align = vs;
|
||||
}
|
||||
return align_up(tag_sz, payload_align);
|
||||
}
|
||||
return 0;
|
||||
|
||||
const spl_layout_info_t *info = ir_layout(ctx, tid);
|
||||
if (!info || idx >= vec_size(info->field_bit_offsets))
|
||||
return 0;
|
||||
return vec_at(info->field_bit_offsets, idx) / 8;
|
||||
}
|
||||
|
||||
static int get_or_add_native(spl_ir2vm_t *ctx, const char *name) {
|
||||
@@ -752,12 +713,31 @@ static void cg_typeop(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
case SPL_IR_TYPE_SIZEOF:
|
||||
v = ir_type_size(ctx, n->ir_sizeof.tid);
|
||||
break;
|
||||
case SPL_IR_TYPE_BITSIZEOF:
|
||||
v = ir_type_size(ctx, n->bitsizeof.tid) * 8;
|
||||
case SPL_IR_TYPE_BITSIZEOF: {
|
||||
const spl_layout_info_t *info = ir_layout(ctx, n->bitsizeof.tid);
|
||||
v = info ? info->size_bits : 0;
|
||||
break;
|
||||
}
|
||||
case SPL_IR_TYPE_ALIGNOF:
|
||||
v = ir_type_size(ctx, n->ir_alignof.tid);
|
||||
v = ir_type_align(ctx, n->ir_alignof.tid);
|
||||
break;
|
||||
case SPL_IR_TYPE_OFFSETOF: {
|
||||
usize idx = 0;
|
||||
if (n->ir_offsetof.field_idx < vec_size(cg->irf->nodes)) {
|
||||
const spl_ir_node_t *idx_node = &vec_at(cg->irf->nodes, n->ir_offsetof.field_idx);
|
||||
if (idx_node->kind == SPL_IR_TYPE_CONST)
|
||||
idx = (usize)idx_node->type_const.int_lit;
|
||||
}
|
||||
v = ir_agg_field_off(ctx, n->ir_offsetof.tid, idx);
|
||||
break;
|
||||
}
|
||||
case SPL_IR_TYPE_FIELD_COUNT: {
|
||||
spl_type_node_t *tn = spl_type_node(ctx->type, n->field_count.tid);
|
||||
if (tn && (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_UNION ||
|
||||
tn->kind == SPL_TYPE_ENUM || tn->kind == SPL_TYPE_SHAPE))
|
||||
v = vec_size(tn->agg_type.variants);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -1028,6 +1008,8 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) {
|
||||
case SPL_IR_TYPE_SIZEOF:
|
||||
case SPL_IR_TYPE_BITSIZEOF:
|
||||
case SPL_IR_TYPE_ALIGNOF:
|
||||
case SPL_IR_TYPE_OFFSETOF:
|
||||
case SPL_IR_TYPE_FIELD_COUNT:
|
||||
cg_typeop(cg, ref, n);
|
||||
break;
|
||||
|
||||
@@ -1142,11 +1124,12 @@ 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) {
|
||||
spl_layout_t *layout, const spl_attr_t *attr) {
|
||||
Assert(ir != NULL && type != NULL && attr != NULL);
|
||||
ctx->ir = ir;
|
||||
ctx->type = type;
|
||||
ctx->attr = attr;
|
||||
ctx->layout = layout;
|
||||
map_init(ctx->extern_native, spl_map_hash, spl_map_cmp);
|
||||
spl_prog_init(&ctx->prog);
|
||||
|
||||
|
||||
+3
-1
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "spl_diag.h"
|
||||
#include "spl_ir.h"
|
||||
#include "spl_layout.h"
|
||||
#include "spl_type.h"
|
||||
|
||||
#include "../stage0/spl_mcode.h"
|
||||
@@ -21,12 +22,13 @@ typedef struct {
|
||||
const spl_attr_t *attr;
|
||||
spl_extern_idx_map_t extern_native;
|
||||
spl_prog_t prog;
|
||||
spl_layout_t *layout; /* 借用 splc0 的 layout(size/align/offset 唯一来源) */
|
||||
|
||||
spl_diag_t *diag;
|
||||
} spl_ir2vm_t;
|
||||
|
||||
void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type,
|
||||
const spl_attr_t *attr);
|
||||
spl_layout_t *layout, const spl_attr_t *attr);
|
||||
void spl_ir2vm_drop(spl_ir2vm_t *ctx);
|
||||
|
||||
int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref);
|
||||
|
||||
+39
-13
@@ -50,8 +50,9 @@ void spl_layout_init(spl_layout_t *layout, spl_layout_target_t *target) {
|
||||
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);
|
||||
usize ps = target && target->ptr_size ? target->ptr_size : sizeof(void *);
|
||||
usize pa = target && target->ptr_align ? target->ptr_align : sizeof(void *);
|
||||
spl_layout_add_ptr(layout, 0, ps, pa);
|
||||
}
|
||||
|
||||
void spl_layout_drop(spl_layout_t *layout) {
|
||||
@@ -145,6 +146,8 @@ static bool layout_agg(spl_layout_t *layout, spl_type_node_t *tn, spl_layout_inf
|
||||
|
||||
for (usize i = 0; i < n; ++i) {
|
||||
spl_type_member_t *m = &vec_at(tn->agg_type.variants, i);
|
||||
if (m->type_id == 0) /* 无载荷变体 */
|
||||
continue;
|
||||
spl_layout_info_t *fi = infos_at(layout, m->type_id);
|
||||
if (!fi || !fi->resolved)
|
||||
return false;
|
||||
@@ -160,6 +163,21 @@ static bool layout_agg(spl_layout_t *layout, spl_type_node_t *tn, spl_layout_inf
|
||||
tag_align_bits > payload_align_bits ? tag_align_bits : payload_align_bits;
|
||||
out->size_bits = round_up_bits(payload_off + payload_size_bits, final_align_bits);
|
||||
out->align_bits = final_align_bits;
|
||||
|
||||
/* 字段索引约定(与 ir2vm 一致):0 = tag,1..n = 各变体载荷(同一偏移)。 */
|
||||
vec_push(out->field_bit_offsets, 0);
|
||||
vec_push(out->field_bit_sizes, tag_info->size_bits);
|
||||
for (usize i = 0; i < n; ++i) {
|
||||
spl_type_member_t *m = &vec_at(tn->agg_type.variants, i);
|
||||
usize fsize = 0;
|
||||
if (m->type_id) {
|
||||
spl_layout_info_t *fi = infos_at(layout, m->type_id);
|
||||
if (fi)
|
||||
fsize = fi->size_bits;
|
||||
}
|
||||
vec_push(out->field_bit_offsets, payload_off);
|
||||
vec_push(out->field_bit_sizes, fsize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -175,22 +193,27 @@ static bool layout_agg(spl_layout_t *layout, spl_type_node_t *tn, spl_layout_inf
|
||||
|
||||
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;
|
||||
usize fsize_bits = 0;
|
||||
usize fsize_align = 8;
|
||||
if (m->type_id) {
|
||||
spl_layout_info_t *fi = infos_at(layout, m->type_id);
|
||||
if (!fi || !fi->resolved)
|
||||
return false;
|
||||
fsize_bits = fi->size_bits;
|
||||
fsize_align = fi->align_bits ? fi->align_bits : 8;
|
||||
}
|
||||
usize field_align_bits = fsize_align;
|
||||
|
||||
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;
|
||||
vec_push(out->field_bit_sizes, fsize_bits);
|
||||
if (fsize_bits > out->size_bits)
|
||||
out->size_bits = fsize_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;
|
||||
vec_push(out->field_bit_sizes, fsize_bits);
|
||||
offset_bits += fsize_bits;
|
||||
}
|
||||
if (field_align_bits > max_align_bits)
|
||||
max_align_bits = field_align_bits;
|
||||
@@ -266,9 +289,12 @@ static void resolve_type(spl_layout_t *layout, spl_type_t *type, spl_type_id_t i
|
||||
case SPL_TYPE_UNION:
|
||||
case SPL_TYPE_ENUM:
|
||||
case SPL_TYPE_SHAPE: {
|
||||
if (tn->kind == SPL_TYPE_ENUM && tn->agg_type.tag_type)
|
||||
resolve_type(layout, type, tn->agg_type.tag_type);
|
||||
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);
|
||||
if (m->type_id)
|
||||
resolve_type(layout, type, m->type_id);
|
||||
}
|
||||
layout_agg(layout, tn, info);
|
||||
return;
|
||||
|
||||
+2
-1
@@ -32,7 +32,8 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
enum { SPL_BIG_ENDIAN, SPL_LITTLE_ENDIAN } endian; // TODO 更多位存储方式
|
||||
|
||||
usize ptr_size;
|
||||
usize ptr_align;
|
||||
} spl_layout_target_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
+55
-7
@@ -938,9 +938,9 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
case SPL_INTRIN_TRUNCATE:
|
||||
case SPL_INTRIN_BIT_CAST:
|
||||
case SPL_INTRIN_FLOAT_CAST:
|
||||
case SPL_INTRIN_INT_FROM_FLOAT:
|
||||
case SPL_INTRIN_FLOAT_FROM_INT:
|
||||
case SPL_INTRIN_PTR_FROM_INT:
|
||||
case SPL_INTRIN_FLOAT2INT:
|
||||
case SPL_INTRIN_INT2FLOAT:
|
||||
case SPL_INTRIN_INT2PTR:
|
||||
case SPL_INTRIN_PTR_CAST: {
|
||||
spl_lang_type_id_t src_lang = sema_infer(sema, vec_at(*args, 0));
|
||||
if (!src_lang)
|
||||
@@ -959,8 +959,8 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
n->resolved_lang_tid = dst_lang;
|
||||
return dst_lang;
|
||||
}
|
||||
case SPL_INTRIN_INT_FROM_BOOL:
|
||||
case SPL_INTRIN_INT_FROM_PTR: {
|
||||
case SPL_INTRIN_BOOL2INT:
|
||||
case SPL_INTRIN_PTR2INT: {
|
||||
sema_infer(sema, vec_at(*args, 0));
|
||||
if (nargs >= 2) {
|
||||
spl_lang_type_id_t dst = sema_infer(sema, vec_at(*args, 1));
|
||||
@@ -973,6 +973,53 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
n->resolved_lang_tid = r;
|
||||
return r;
|
||||
}
|
||||
case SPL_INTRIN_ENUM2INT: {
|
||||
spl_lang_type_id_t src = sema_infer(sema, vec_at(*args, 0));
|
||||
if (!src)
|
||||
return 0;
|
||||
spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src);
|
||||
if (!sn || sn->kind != SPL_LANG_TYPE_ENUM) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"@enum2int requires an enum operand");
|
||||
return 0;
|
||||
}
|
||||
spl_type_node_t *sir = spl_type_node(&sema->type->ir, sn->ir_type_id);
|
||||
if (!sir || !sir->agg_type.tag_type) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTERNAL, &n->dbg,
|
||||
"@enum2int: enum has no tag type");
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t tag = sema_lang_from_ir(sema, sir->agg_type.tag_type);
|
||||
n->resolved_lang_tid = tag;
|
||||
return tag;
|
||||
}
|
||||
case SPL_INTRIN_FIELD_COUNT: {
|
||||
if (!sema_infer_type_context(sema, vec_at(*args, 0)))
|
||||
return 0;
|
||||
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
|
||||
}
|
||||
case SPL_INTRIN_OFFSETOF: {
|
||||
spl_lang_type_id_t agg_lang = sema_infer_type_context(sema, vec_at(*args, 0));
|
||||
if (!agg_lang)
|
||||
return 0;
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang);
|
||||
spl_ast_node_t *fnode = spl_ast_node(sema->ast, vec_at(*args, 1));
|
||||
if (!fnode)
|
||||
return 0;
|
||||
if (fnode->kind == SPL_AST_EXPR_IDENT) {
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, fnode->ident.name, &idx)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg, "no field `%s`",
|
||||
fnode->ident.name);
|
||||
return 0;
|
||||
}
|
||||
} else if (fnode->kind != SPL_AST_EXPR_INT_LIT) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"@offsetof expects a field name or integer index");
|
||||
return 0;
|
||||
}
|
||||
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -2718,11 +2765,12 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope,
|
||||
spl_attr_t *attr) {
|
||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_layout_t *layout,
|
||||
spl_scope_t *scope, spl_attr_t *attr) {
|
||||
Assert(sema != NULL && ast != NULL && type != NULL && scope != NULL && attr != NULL);
|
||||
sema->ast = ast;
|
||||
sema->type = type;
|
||||
sema->layout = layout;
|
||||
sema->scope = scope;
|
||||
sema->current_fn_ret_tid = 0;
|
||||
sema->current_aggregate_lang = 0;
|
||||
|
||||
+4
-2
@@ -5,6 +5,7 @@
|
||||
#include "spl_attr.h"
|
||||
#include "spl_diag.h"
|
||||
#include "spl_lang_type.h"
|
||||
#include "spl_layout.h"
|
||||
#include "spl_mpa.h"
|
||||
#include "spl_scope.h"
|
||||
#include "spl_type.h"
|
||||
@@ -21,6 +22,7 @@ struct spl_module_loader {
|
||||
typedef struct {
|
||||
spl_ast_t *ast;
|
||||
spl_lang_type_t *type;
|
||||
spl_layout_t *layout; /* 由 splc0 拥有并解析;sema 仅借用 */
|
||||
spl_scope_t *scope;
|
||||
spl_symbol_t root;
|
||||
spl_attr_t *attr;
|
||||
@@ -32,8 +34,8 @@ typedef struct {
|
||||
spl_diag_t *diag;
|
||||
} spl_sema_t;
|
||||
|
||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope,
|
||||
spl_attr_t *attr);
|
||||
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type,
|
||||
spl_layout_t *layout, spl_scope_t *scope, spl_attr_t *attr);
|
||||
void spl_sema_drop(spl_sema_t *sema);
|
||||
|
||||
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref);
|
||||
|
||||
+20
-4
@@ -182,6 +182,8 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
|
||||
spl_attr_t attr;
|
||||
spl_lang_type_t lang_type;
|
||||
spl_layout_target_t layout_target;
|
||||
spl_layout_t layout;
|
||||
spl_scope_t scope;
|
||||
spl_sema_t sema;
|
||||
spl_ast2ir_t a2ir;
|
||||
@@ -189,7 +191,7 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
spl_ir2vm_t ir2vm;
|
||||
spl_ast_ptr_vec_t all_asts;
|
||||
|
||||
int attr_ok = 0, lang_type_ok = 0, scope_ok = 0;
|
||||
int attr_ok = 0, lang_type_ok = 0, layout_ok = 0, scope_ok = 0;
|
||||
int sema_ok = 0, a2ir_ok = 0, irb_ok = 0, ir2vm_ok = 0;
|
||||
|
||||
spl_diag_set_stage(&diag, SPL_STAGE_PARSE);
|
||||
@@ -212,10 +214,19 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
attr_ok = 1;
|
||||
spl_lang_type_init(&lang_type);
|
||||
lang_type_ok = 1;
|
||||
|
||||
/* 目标描述符:剥离目标机器细节,layout 是 size/align/offset 的唯一来源。 */
|
||||
memset(&layout_target, 0, sizeof layout_target);
|
||||
layout_target.endian = SPL_LITTLE_ENDIAN;
|
||||
layout_target.ptr_size = sizeof(void *);
|
||||
layout_target.ptr_align = sizeof(void *);
|
||||
spl_layout_init(&layout, &layout_target);
|
||||
layout_ok = 1;
|
||||
|
||||
spl_scope_init(&scope);
|
||||
scope_ok = 1;
|
||||
|
||||
spl_sema_init(&sema, &drv.main_ast, &lang_type, &scope, &attr);
|
||||
spl_sema_init(&sema, &drv.main_ast, &lang_type, &layout, &scope, &attr);
|
||||
sema_ok = 1;
|
||||
spl_module_loader_t loader = {.load = driver_load, .user = &drv};
|
||||
sema.loader = &loader;
|
||||
@@ -242,7 +253,7 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
|
||||
spl_ir_builder_init(&ir_builder);
|
||||
irb_ok = 1;
|
||||
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
|
||||
spl_ast2ir_init(&a2ir, &ir_builder, &layout, &sema);
|
||||
a2ir_ok = 1;
|
||||
spl_diag_set_stage(&diag, SPL_STAGE_AST2IR);
|
||||
a2ir.diag = &diag;
|
||||
@@ -257,7 +268,10 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &lang_type.ir, &attr);
|
||||
/* 类型已全部就绪:解析 layout,供 ir2vm 的 size/align/offset 使用。 */
|
||||
spl_layout_resolve(&layout, &lang_type.ir);
|
||||
|
||||
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &lang_type.ir, &layout, &attr);
|
||||
ir2vm_ok = 1;
|
||||
spl_diag_set_stage(&diag, SPL_STAGE_IR2VM);
|
||||
ir2vm.diag = &diag;
|
||||
@@ -285,6 +299,8 @@ cleanup:
|
||||
spl_sema_drop(&sema);
|
||||
if (scope_ok)
|
||||
spl_scope_drop(&scope);
|
||||
if (layout_ok)
|
||||
spl_layout_drop(&layout);
|
||||
if (lang_type_ok)
|
||||
spl_lang_type_drop(&lang_type);
|
||||
if (attr_ok)
|
||||
|
||||
Reference in new issue
Block a user