feat(ast2ir): 添加数组初始化支持和AST转IR优化

添加了对未知长度数组的自动长度推导功能,支持字符串字面量和复合
初始化的数组长度计算。新增辅助函数resolve_array_length用于计算
数组实际长度,以及emit_array_initialization用于生成数组初始化
代码。

同时将AST转IR过程中的参数改为const引用,提高代码安全性。
新增IR构建器的借用检查机制,防止在借用期间进行重分配操作。

fix(ast): 为AST结构体添加详细注释说明字段用途
This commit is contained in:
zzy
2026-04-13 11:36:52 +08:00
parent 694778e4a0
commit ffb23afaf4
13 changed files with 480 additions and 220 deletions

View File

@@ -328,7 +328,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
}
} else {
// TODO
parse_value(ctx, value->data.get_elem_ptr.index, patches);
// parse_value(ctx, value->data.get_elem_ptr.index, patches);
scc_reg_loc_t src_loc;
scc_reg_loc_t idx_loc;
@@ -337,8 +337,21 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX);
// 获取 src_addr 所指向的类型的元素大小
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
scc_ir_type_t *base_type = scc_ir_module_get_type(
GET_MODULE(ctx), ptr_type->data.pointer.base);
scc_ir_type_t ir_type = *base_type;
if (ir_type.tag == SCC_IR_TYPE_ARRAY) {
ir_type.tag = SCC_IR_TYPE_PTR;
}
int elem_size = scc_ir2mcode_type_width(GET_MODULE(ctx), &ir_type);
// 然后生成 LEA 时使用 scale = elem_size
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0);
SCC_AMD64_RAX, SCC_AMD64_RDX,
elem_size, 0);
}
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
break;
@@ -483,28 +496,36 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
///< 调用函数
case SCC_IR_VALUE_TAG_CALL: {
scc_reg_loc_t loc;
/*
ABI
RAX 不稳定的 返回值寄存器
RCX 不稳定的 第一个整型自变量
RDX 不稳定的 第二个整型自变量
R8 不稳定的 第三个整型自变量
R9 不稳定的 第四个整型自变量
*/
scc_vec_foreach(value->data.call.args, i) {
usize nargs = scc_vec_size(value->data.call.args);
// 影子空间 32 字节 + 每个额外参数 8 字节(按 8 字节对齐)
usize stack_args_count = (nargs > 4) ? (nargs - 4) : 0;
usize stack_args_size = stack_args_count * 8;
usize total_stack_alloc = 32 + stack_args_size;
// 调整栈指针(保持 16 字节对齐)
if (total_stack_alloc > 0) {
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
}
// 处理寄存器参数(前 4 个)
for (usize i = 0; i < nargs && i < 4; i++) {
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
if (i == 0) {
load_value_to_reg(ctx, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
load_value_to_reg(ctx, &loc, SCC_AMD64_RDX);
} else if (i == 2) {
load_value_to_reg(ctx, &loc, SCC_AMD64_R8);
} else if (i == 3) {
load_value_to_reg(ctx, &loc, SCC_AMD64_R9);
} else {
LOG_FATAL("not support more than 4 args");
}
// scc_mcode_amd64_push_r64();
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
SCC_AMD64_R9};
load_value_to_reg(ctx, &loc, reg[i]);
}
// 处理栈参数(第 5 个及以后)
// 从右向左依次写入栈(即最后一个参数放在最高地址)
for (usize i = 4; i < nargs; i++) {
scc_reg_loc_t loc;
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
// 加载到临时寄存器(如 RAX
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
// 计算栈偏移:影子空间(32) + (i-4)*8
int offset = 32 + (i - 4) * 8;
scc_mcode_amd64_mov_m64_disp32_r64(&ctx->sect_mcode, SCC_AMD64_RSP,
offset, SCC_AMD64_RAX);
}
scc_ir_func_t *func =
@@ -530,7 +551,10 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
// 恢复栈指针
if (total_stack_alloc > 0) {
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
}
// 处理返回值
scc_ir_type_t *func_type =
scc_ir_module_get_type(GET_MODULE(ctx), func->type);
@@ -604,22 +628,22 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
SCC_AMD64_RSP, ctx->stack_size);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
// scc_ir_value_t *param =
// scc_ir_module_get_value(GET_MODULE(ctx), );
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
parse_location(ctx, &loc, node_ref);
if (i == 0) {
store_value_from_reg(ctx, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
store_value_from_reg(ctx, &loc, SCC_AMD64_RDX);
} else if (i == 2) {
store_value_from_reg(ctx, &loc, SCC_AMD64_R8);
} else if (i == 3) {
store_value_from_reg(ctx, &loc, SCC_AMD64_R9);
if (i < 4) {
// 前 4 个参数:从寄存器存入槽位
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
SCC_AMD64_R9};
store_value_from_reg(ctx, &loc, reg[i]);
} else {
LOG_FATAL("not support more than 4 args");
// 额外参数:从栈中加载到槽位
// 偏移 = 16 (old rbp+retaddr) + 32 (shadow) + (i-4)*8
int offset = 16 + 32 + (i - 4) * 8;
// 临时将栈值加载到 RAX再存储到槽位
scc_mcode_amd64_mov_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RBP, offset);
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
}
// scc_mcode_amd64_push_r64();
}
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
@@ -759,6 +783,4 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
sccf_builder_add_text_section(ctx->builder, &text_section);
sccf_builder_add_data_section(ctx->builder, &ctx->sect_data);
// FIXME maybe _entry and add crt
ctx->builder->entry_symbol_name = "main";
}