stage2 更多底层函数 stage1 layout正确使用 内置函数重新编写

This commit is contained in:
zzy committed 2026-09-17 22:03:23 +08:00
1 parent fb0ff9b663
commit 4141e7d574
15 files changed
+2588 -122

No files matched your search

+47 -11
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)