feat(ir): 重构指针操作API并优化数组访问逻辑

- 将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函数的大字符串处理性能

- 实现动态缓冲区分配策略,小字符串使用栈缓冲区,大字符串使用堆分配
- 避免固定大小缓冲区可能导致的截断问题
- 添加适当的内存清理机制
This commit is contained in:
zzy
2026-04-11 10:12:22 +08:00
parent eeb4c4fc3c
commit 053c6abf51
9 changed files with 106 additions and 63 deletions

View File

@@ -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 创建二元运算指令

View File

@@ -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;

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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;