From 053c6abf51efd47e1d3e5d777d39d83f36268568 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sat, 11 Apr 2026 10:12:22 +0800 Subject: [PATCH] =?UTF-8?q?feat(ir):=20=E9=87=8D=E6=9E=84=E6=8C=87?= =?UTF-8?q?=E9=92=88=E6=93=8D=E4=BD=9CAPI=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E8=AE=BF=E9=97=AE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将scc_ir_builder_get_ptr重命名为scc_ir_builder_get_elem_ptr以更好地反映其功能 - 移除旧的GET_PTR相关枚举和结构体定义 - 更新IR构建器中指针类型的处理逻辑,支持数组元素指针计算 - 在代码生成阶段正确处理元素指针操作的索引计算 fix(ast2ir): 修正数组下标表达式的指针获取操作 - 将数组访问中的get_ptr调用替换为get_elem_ptr - 确保数组元素访问使用正确的IR指令 perf(runtime): 优化fprintf函数的大字符串处理性能 - 实现动态缓冲区分配策略,小字符串使用栈缓冲区,大字符串使用堆分配 - 避免固定大小缓冲区可能导致的截断问题 - 添加适当的内存清理机制 --- libs/ast2ir/src/scc_ast2ir.c | 8 ++++--- libs/ir/include/ir_builder.h | 17 ++++++++------- libs/ir/include/ir_def.h | 5 ----- libs/ir/src/ir_builder.c | 34 ++++++++++++++++++++--------- libs/ir/src/ir_dump.c | 26 ++++++++++------------ libs/ir/src/scc_ir.c | 6 +++--- libs/ir2mcode/src/ir2amd64.c | 37 ++++++++++++++++++-------------- libs/ir2mcode/src/reg_alloc.c | 1 - runtime/scc_core/src/core_impl.c | 35 ++++++++++++++++++++++++++++-- 9 files changed, 106 insertions(+), 63 deletions(-) diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 3f8b25a..a55a900 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -1,5 +1,7 @@ #include +static inline void parse_struct_union_layout(scc_ast_type_t *type) {} + static inline void parse_lexme2const_int(const char *lexme, scc_ir_const_int_t *value) { // FIXME @@ -430,7 +432,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, scc_ast2ir_expr(ctx, expr->subscript.index, false); // 3. 生成 getptr(GEP) scc_ir_value_ref_t elem_ptr = - scc_ir_builder_get_ptr(&ctx->builder, base_ptr, index); + scc_ir_builder_get_elem_ptr(&ctx->builder, base_ptr, index); // 4. 根据左值/右值返回 if (is_lvalue) { return elem_ptr; // 作为左值:返回地址 @@ -523,8 +525,8 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, ctx->builder.ctx.module, ir_type->data.pointer.base); if (target_type->tag == SCC_IR_TYPE_ARRAY) { // 生成 getptr 获取数组首地址 - return scc_ir_builder_get_ptr(&ctx->builder, in, - SCC_IR_REF_nullptr); + return scc_ir_builder_get_elem_ptr(&ctx->builder, in, + SCC_IR_REF_nullptr); } else { // 标量类型:加载值 return scc_ir_builder_load(&ctx->builder, in); diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index b6cddf6..e8d249c 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -144,11 +144,12 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str, // scc_hashtable_insert(builder); scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value( - builder->ctx.module, &(scc_ir_value_t){ - .tag = SCC_IR_VALUE_TAG_GET_PTR, - .data.get_ptr.src_addr = global_value_ref, - .data.get_ptr.index = SCC_IR_VALUE_TAG_NULLPTR, - }); + builder->ctx.module, + &(scc_ir_value_t){ + .tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR, + .data.get_elem_ptr.src_addr = global_value_ref, + .data.get_elem_ptr.index = SCC_IR_VALUE_TAG_NULLPTR, + }); scc_ir_builder_add_instr(builder, pointer_to_global_value); return pointer_to_global_value; } @@ -236,9 +237,9 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, * @param ptr 基础指针 * @param index 索引值 */ -scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder, - scc_ir_value_ref_t ptr, - scc_ir_value_ref_t index); +scc_ir_value_ref_t scc_ir_builder_get_elem_ptr(scc_ir_builder_t *builder, + scc_ir_value_ref_t ptr, + scc_ir_value_ref_t index); /** * @brief 创建二元运算指令 diff --git a/libs/ir/include/ir_def.h b/libs/ir/include/ir_def.h index 4ee5684..8531d5c 100644 --- a/libs/ir/include/ir_def.h +++ b/libs/ir/include/ir_def.h @@ -100,7 +100,6 @@ typedef enum scc_ir_value_tag { SCC_IR_VALUE_TAG_GLOBAL_ALLOC, ///< 全局分配 SCC_IR_VALUE_TAG_LOAD, ///< 加载数据 SCC_IR_VALUE_TAG_STORE, ///< 存储数据 - SCC_IR_VALUE_TAG_GET_PTR, ///< 获取指针 SCC_IR_VALUE_TAG_GET_ELEM_PTR, ///< 获取元素指针 SCC_IR_VALUE_TAG_OP, ///< 二元运算 SCC_IR_VALUE_TAG_BRANCH, ///< 有条件分支 @@ -258,10 +257,6 @@ struct scc_ir_value { scc_ir_value_ref_t target; scc_ir_value_ref_t value; } store; - struct { - scc_ir_value_ref_t src_addr; - scc_ir_value_ref_t index; - } get_ptr; struct { scc_ir_value_ref_t src_addr; scc_ir_value_ref_t index; diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index 77491fd..2776fe1 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -227,19 +227,33 @@ scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, return value_ref; } -scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder, - scc_ir_value_ref_t target, - scc_ir_value_ref_t index) { +scc_ir_value_ref_t scc_ir_builder_get_elem_ptr(scc_ir_builder_t *builder, + scc_ir_value_ref_t target, + scc_ir_value_ref_t index) { scc_ir_value_t get_ptr_node = {0}; - get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_PTR; - get_ptr_node.data.get_ptr.src_addr = target; - get_ptr_node.data.get_ptr.index = index; + get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_ELEM_PTR; + get_ptr_node.data.get_elem_ptr.src_addr = target; + get_ptr_node.data.get_elem_ptr.index = index; // 类型应与源地址相同(都是指针) - scc_ir_value_t *src_node = - scc_ir_module_get_value(GET_MODULE(builder), target); - if (src_node) { - get_ptr_node.type = src_node->type; + scc_ir_type_t *type = + scc_ir_module_get_type_by_value(GET_MODULE(builder), target); + Assert(type != nullptr); + if (type->tag == SCC_IR_TYPE_PTR) { + scc_ir_type_t *base_type = scc_ir_module_get_type( + GET_MODULE(builder), type->data.pointer.base); + if (base_type->tag == SCC_IR_TYPE_ARRAY) { + // FIXME GEP maybe multiple levels + get_ptr_node.type = scc_ir_builder_type( + builder, &(scc_ir_type_t){ + .tag = SCC_IR_TYPE_PTR, + .data.pointer.base = base_type->data.array.base, + }); + } else { + get_ptr_node.type = scc_ir_builder_type(builder, type); + } + } else { + get_ptr_node.type = scc_ir_builder_type(builder, type); } scc_ir_value_ref_t value_ref = diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index dd2b6e6..ce08d35 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -20,7 +20,6 @@ static const char *get_node_type_str(scc_ir_value_tag_t tag) { [SCC_IR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc", [SCC_IR_VALUE_TAG_LOAD] = "Load", [SCC_IR_VALUE_TAG_STORE] = "Store", - [SCC_IR_VALUE_TAG_GET_PTR] = "GetPtr", [SCC_IR_VALUE_TAG_GET_ELEM_PTR] = "GetElemPtr", [SCC_IR_VALUE_TAG_OP] = "Op", [SCC_IR_VALUE_TAG_BRANCH] = "Branch", @@ -117,12 +116,12 @@ static void dump_store_node(scc_ir_dump_ctx_t *ctx, dump_child_node_ref(ctx, value->data.store.value, true); } -static void dump_get_ptr_node(scc_ir_dump_ctx_t *ctx, - const scc_ir_value_t *value) { - if (value->data.get_ptr.src_addr) - dump_child_node_ref(ctx, value->data.get_ptr.src_addr, false); - if (value->data.get_ptr.index) - dump_child_node_ref(ctx, value->data.get_ptr.index, true); +static void dump_get_elem_ptr_node(scc_ir_dump_ctx_t *ctx, + const scc_ir_value_t *value) { + if (value->data.get_elem_ptr.src_addr) + dump_child_node_ref(ctx, value->data.get_elem_ptr.src_addr, false); + if (value->data.get_elem_ptr.index) + dump_child_node_ref(ctx, value->data.get_elem_ptr.index, true); } static void dump_branch_node(scc_ir_dump_ctx_t *ctx, @@ -236,8 +235,8 @@ void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t value_ref) { case SCC_IR_VALUE_TAG_STORE: dump_store_node(ctx, value); break; - case SCC_IR_VALUE_TAG_GET_PTR: - dump_get_ptr_node(ctx, value); + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: + dump_get_elem_ptr_node(ctx, value); break; case SCC_IR_VALUE_TAG_OP: dump_op_node(ctx, value); @@ -556,13 +555,10 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx, format_ref_or_value(ctx, value->data.store.target); break; case SCC_IR_VALUE_TAG_GET_ELEM_PTR: - case SCC_IR_VALUE_TAG_GET_PTR: - scc_tree_dump_append( - ctx->dump_ctx, - value->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr " : "getelemptr "); - format_ref_or_value(ctx, value->data.get_ptr.src_addr); + scc_tree_dump_append(ctx->dump_ctx, "getelemptr "); + format_ref_or_value(ctx, value->data.get_elem_ptr.src_addr); scc_tree_dump_append(ctx->dump_ctx, ", "); - format_ref_or_value(ctx, value->data.get_ptr.index); + format_ref_or_value(ctx, value->data.get_elem_ptr.index); break; case SCC_IR_VALUE_TAG_OP: format_ref_or_value(ctx, value->data.op.lhs); diff --git a/libs/ir/src/scc_ir.c b/libs/ir/src/scc_ir.c index 8580940..33edede 100644 --- a/libs/ir/src/scc_ir.c +++ b/libs/ir/src/scc_ir.c @@ -82,9 +82,9 @@ void scc_ir_value_init(scc_ir_value_t *in, const char *name, in->data.store.target = 0; in->data.store.value = 0; break; - case SCC_IR_VALUE_TAG_GET_PTR: - in->data.get_ptr.src_addr = 0; - in->data.get_ptr.index = 0; + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: + in->data.get_elem_ptr.src_addr = 0; + in->data.get_elem_ptr.index = 0; break; case SCC_IR_VALUE_TAG_OP: in->data.op.op = SCC_IR_OP_EMPTY; diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index 7b0efac..9be35da 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -287,14 +287,14 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, break; } ///< 获取指针 - case SCC_IR_VALUE_TAG_GET_PTR: { + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: { scc_reg_loc_t loc_res; parse_location(ctx, &loc_res, node_ref); scc_ir_value_t *src_addr = scc_ir_module_get_value( - GET_MODULE(ctx), value->data.get_ptr.src_addr); + GET_MODULE(ctx), value->data.get_elem_ptr.src_addr); Assert(src_addr != nullptr); - if (value->data.get_ptr.index == 0) { + if (value->data.get_elem_ptr.index == 0) { if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) { // 全局变量:RIP相对寻址 scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, @@ -314,30 +314,35 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, } else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) { // 栈上变量:地址为 rbp - offset scc_reg_loc_t src_loc; - parse_location(ctx, &src_loc, value->data.get_ptr.src_addr); + parse_location(ctx, &src_loc, + value->data.get_elem_ptr.src_addr); src_loc.kind = SCC_REG_KIND_STACK_ADDR; load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); } else { - // 其他情况(如链式 - // getptr):源地址值已经存储在某个位置,直接加载到 RAX + // 其他情况(如链式getptr):源地址值已经存储在某个位置,直接加载到 + // RAX scc_reg_loc_t src_loc; - parse_location(ctx, &src_loc, value->data.get_ptr.src_addr); + parse_location(ctx, &src_loc, + value->data.get_elem_ptr.src_addr); load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); } - - store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX); } else { // TODO - scc_ir_value_t *index = scc_ir_module_get_value( - GET_MODULE(ctx), value->data.get_ptr.index); - Assert(index != nullptr && - index->tag == SCC_IR_VALUE_TAG_CONST_INT); - } + parse_value(ctx, value->data.get_elem_ptr.index, patches); + scc_reg_loc_t src_loc; + scc_reg_loc_t idx_loc; + parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr); + parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index); + 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); + scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0); + } + store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX); break; } - case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array) - TODO(); ///< 二元运算 case SCC_IR_VALUE_TAG_OP: { scc_reg_loc_t loc_lhs; diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c index 619a998..c5927a1 100644 --- a/libs/ir2mcode/src/reg_alloc.c +++ b/libs/ir2mcode/src/reg_alloc.c @@ -49,7 +49,6 @@ void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx, switch (node->tag) { case SCC_IR_VALUE_TAG_LOAD: case SCC_IR_VALUE_TAG_OP: - case SCC_IR_VALUE_TAG_GET_PTR: case SCC_IR_VALUE_TAG_GET_ELEM_PTR: case SCC_IR_VALUE_TAG_CALL: // 返回值 loc.kind = SCC_REG_KIND_STACK; diff --git a/runtime/scc_core/src/core_impl.c b/runtime/scc_core/src/core_impl.c index 1bcc450..0a8d4b7 100644 --- a/runtime/scc_core/src/core_impl.c +++ b/runtime/scc_core/src/core_impl.c @@ -79,8 +79,33 @@ int scc_fprintf(scc_file_t file, const char *format, ...) { } int scc_vfprintf(scc_file_t file, const char *format, va_list args) { - char buf[4096] = {0}; - int size = vsnprintf_(buf, sizeof(buf), format, args); + va_list args_copy; + va_copy(args_copy, args); + + // 先计算所需长度 + int required_size = vsnprintf_(nullptr, 0, format, args_copy); + va_end(args_copy); + + if (required_size < 0) + return -1; + + char *buf = nullptr; + int size = 0; + + if (required_size < 4096) { + // 小输出使用栈上缓冲区 + char stack_buf[4096]; + size = vsnprintf_(stack_buf, sizeof(stack_buf), format, args); + buf = stack_buf; + } else { + // 大输出使用堆分配 + buf = scc_pal_malloc(required_size + 1); + if (!buf) + return -1; + size = vsnprintf_(buf, required_size + 1, format, args); + } + + // 输出处理... if (file == scc_stdout) { scc_pal_write(buf, size); } else if (file == scc_stderr) { @@ -88,6 +113,12 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) { } else { scc_pal_fwrite(file, buf, size); } + + // 如果使用了堆分配,释放内存 + if (buf && required_size >= 4096) { + scc_pal_free(buf); + } + return size; }