feat(ir): 添加线性IR转储功能并改进AST转储

- 实现了IR的线性转储功能,包括类型、节点、基本块和函数的线性表示
- 添加了scc_ir_dump_ctx_init函数用于初始化转储上下文
- 为AST函数类型添加了变参标记注释说明
- 改进了AST转储中函数类型的参数和返回值显示逻辑
- 统一了AST解析中节点类型的声明为通用的scc_ast_node_t指针类型

fix(lexer): 改进词法分析器错误信息显示

- 在不支持字符的错误信息中添加十六进制编码显示
- 便于调试时识别特殊不可打印字符
This commit is contained in:
zzy
2026-02-13 09:56:42 +08:00
parent 191cdcef53
commit ffee07a03d
6 changed files with 353 additions and 32 deletions

View File

@@ -238,6 +238,14 @@ static void dump_ret_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
}
}
void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx,
scc_tree_dump_ctx_t *tree_dump, scc_ir_cprog_t *cprog,
scc_ir_cprog_ctx_t *ir_ctx) {
ctx->cprog = cprog;
ctx->dump_ctx = tree_dump;
ctx->ir_ctx = ir_ctx;
}
void scc_ir_dump_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (!node) {
@@ -304,32 +312,6 @@ void scc_ir_dump_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref) {
// 转储类型信息
void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref) {
// impl fmt::Display for TypeKind {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// match self {
// TypeKind::Int32 => write!(f, "i32"),
// TypeKind::Unit => write!(f, "unit"),
// TypeKind::Array(t, len) => write!(f, "[{}, {}]", t, len),
// TypeKind::Pointer(t) => write!(f, "*{}", t),
// TypeKind::Function(params, ret) => {
// write!(f, "(")?;
// let mut first = true;
// for param in params {
// if !first {
// write!(f, ", ")?;
// }
// write!(f, "{}", param)?;
// first = false;
// }
// if !ret.is_unit() {
// write!(f, "): {}", ret)
// } else {
// write!(f, ")")
// }
// }
// }
// }
// }
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
@@ -520,3 +502,324 @@ void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx) {
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
void scc_ir_dump_type_linear(scc_ir_dump_ctx_t *ctx,
scc_ir_type_ref_t type_ref) {
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, type_ref);
if (!ctx || !type) {
LOG_ERROR("invalid parameter");
return;
}
#define PRINT_TYPE(ctx, name) PRINT_VALUE(ctx, "%s", name)
switch (type->tag) {
case SCC_IR_TYPE_I32:
PRINT_TYPE(ctx->dump_ctx, "i32");
break;
case SCC_IR_TYPE_VOID:
PRINT_TYPE(ctx->dump_ctx, "void");
break;
case SCC_IR_TYPE_ARRAY:
PRINT_TYPE(ctx->dump_ctx, "[");
scc_ir_dump_type_linear(ctx, type->data.array.base);
PRINT_TYPE(ctx->dump_ctx, ", ");
PRINT_TYPE(ctx->dump_ctx, type->data.array.len);
PRINT_TYPE(ctx->dump_ctx, "]");
break;
case SCC_IR_TYPE_PTR:
PRINT_TYPE(ctx->dump_ctx, "*");
scc_ir_dump_type_linear(ctx, type->data.pointer.base);
break;
case SCC_IR_TYPE_FUNC:
PRINT_TYPE(ctx->dump_ctx, "(");
cbool is_first = true;
scc_vec_foreach(type->data.function.params, i) {
if (!is_first) {
PRINT_TYPE(ctx->dump_ctx, ", ");
}
scc_ir_dump_type_linear(ctx,
scc_vec_at(type->data.function.params, i));
is_first = false;
}
if (type->data.function.ret_type) {
PRINT_TYPE(ctx->dump_ctx, ") -> ");
scc_ir_dump_type_linear(ctx, type->data.function.ret_type);
} else {
PRINT_TYPE(ctx->dump_ctx, ")");
}
default:
LOG_ERROR("invalid type tag");
break;
}
}
// 辅助函数:输出节点引用或值到缓冲区
static usize format_node_ref_or_value(scc_ir_dump_ctx_t *ctx, char *buf,
usize size, scc_ir_node_ref_t node_ref) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (!node) {
return scc_snprintf(buf, size, "%%%u", node_ref);
}
// 如果是常量整数,直接输出值
if (node->tag == SCC_IR_NODE_CONST_INT) {
return scc_snprintf(buf, size, "%d", node->data.const_int.int32);
}
// 其他节点输出引用和名称
if (node->name && node->name[0] != '\0') {
return scc_snprintf(buf, size, "%%%u[%s]", node_ref, node->name);
} else {
return scc_snprintf(buf, size, "%%%u", node_ref);
}
}
// 线性输出节点信息SSA IR风格
void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
scc_ir_node_ref_t node_ref) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (node == null) {
LOG_ERROR("invalid node ref");
return;
}
static char buff[512]; // 更大的缓冲区处理复杂的指令
char *p = buff;
usize remaining = sizeof(buff);
// 判断是否需要输出等号
cbool needs_equals =
(node->tag != SCC_IR_NODE_BRANCH && node->tag != SCC_IR_NODE_JUMP &&
node->tag != SCC_IR_NODE_RET && node->tag != SCC_IR_NODE_STORE);
if (needs_equals) {
// 输出左值和类型
if (node->name && node->name[0] != '\0') {
p += scc_snprintf(p, remaining, "%%%u[%s]", node_ref, node->name);
} else {
p += scc_snprintf(p, remaining, "%%%u", node_ref);
}
remaining = sizeof(buff) - (p - buff);
if (node->type != 0) {
p += scc_snprintf(p, remaining, " `");
remaining = sizeof(buff) - (p - buff);
// p += dump_type_to_buf(ctx, p, remaining, node->type);
// remaining = sizeof(buff) - (p - buff);
p += scc_snprintf(p, remaining, "`");
remaining = sizeof(buff) - (p - buff);
}
p += scc_snprintf(p, remaining, " = ");
remaining = sizeof(buff) - (p - buff);
}
// 构建操作部分
switch (node->tag) {
case SCC_IR_NODE_CONST_INT:
// 常量节点定义,直接输出值
p += scc_snprintf(p, remaining, "%d", node->data.const_int.int32);
break;
case SCC_IR_NODE_ALLOC:
p += scc_snprintf(p, remaining, "alloc");
break;
case SCC_IR_NODE_LOAD: {
char operand_buf[64];
format_node_ref_or_value(ctx, operand_buf, sizeof(operand_buf),
node->data.load.target);
p += scc_snprintf(p, remaining, "load %s", operand_buf);
break;
}
case SCC_IR_NODE_STORE: {
char value_buf[64], target_buf[64];
format_node_ref_or_value(ctx, value_buf, sizeof(value_buf),
node->data.store.value);
format_node_ref_or_value(ctx, target_buf, sizeof(target_buf),
node->data.store.target);
p +=
scc_snprintf(p, remaining, "store %s -> %s", value_buf, target_buf);
break;
}
case SCC_IR_NODE_GET_PTR: {
char src_buf[64], idx_buf[64];
format_node_ref_or_value(ctx, src_buf, sizeof(src_buf),
node->data.get_ptr.src_addr);
format_node_ref_or_value(ctx, idx_buf, sizeof(idx_buf),
node->data.get_ptr.index);
p += scc_snprintf(p, remaining, "getelemptr %s, %s", src_buf, idx_buf);
break;
}
case SCC_IR_NODE_OP: {
char lhs_buf[64], rhs_buf[64];
format_node_ref_or_value(ctx, lhs_buf, sizeof(lhs_buf),
node->data.op.lhs);
format_node_ref_or_value(ctx, rhs_buf, sizeof(rhs_buf),
node->data.op.rhs);
p += scc_snprintf(p, remaining, "%s %s %s", lhs_buf,
get_op_str(node->data.op.op), rhs_buf);
break;
}
case SCC_IR_NODE_BRANCH:
if (node->data.branch.cond) {
char cond_buf[64];
format_node_ref_or_value(ctx, cond_buf, sizeof(cond_buf),
node->data.branch.cond);
p += scc_snprintf(p, remaining, "br %s, label %%%u, label %%%u",
cond_buf, node->data.branch.true_bblock,
node->data.branch.false_bblock);
} else {
p += scc_snprintf(p, remaining, "br label %%%u",
node->data.branch.true_bblock);
}
break;
case SCC_IR_NODE_JUMP:
p += scc_snprintf(p, remaining, "jmp label %%%u",
node->data.jump.target_bblock);
break;
case SCC_IR_NODE_CALL: {
char args_buf[256] = "";
char *args_p = args_buf;
usize args_remaining = sizeof(args_buf);
for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) {
if (i > 0) {
args_p += scc_snprintf(args_p, args_remaining, ", ");
args_remaining = sizeof(args_buf) - (args_p - args_buf);
}
char arg_buf[64];
format_node_ref_or_value(ctx, arg_buf, sizeof(arg_buf),
scc_vec_at(node->data.call.args, i));
args_p += scc_snprintf(args_p, args_remaining, "%s", arg_buf);
args_remaining = sizeof(args_buf) - (args_p - args_buf);
}
p += scc_snprintf(p, remaining, "call @%%%u(%s)",
node->data.call.callee, args_buf);
break;
}
case SCC_IR_NODE_RET:
if (node->data.ret.ret_val != 0) {
char ret_buf[64];
format_node_ref_or_value(ctx, ret_buf, sizeof(ret_buf),
node->data.ret.ret_val);
p += scc_snprintf(p, remaining, "ret %s", ret_buf);
} else {
p += scc_snprintf(p, remaining, "ret void");
}
break;
default:
p += scc_snprintf(p, remaining, "<%s node %u>",
get_node_type_str(node->tag), node_ref);
break;
}
(void)p;
// 打印完整行
PRINT_NODE(ctx->dump_ctx, buff);
}
// 线性输出基本块信息
void scc_ir_dump_bblock_linear(scc_ir_dump_ctx_t *ctx,
scc_ir_bblock_ref_t bblock_ref) {
scc_ir_bblock_t *bblock = scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref);
if (bblock == null) {
PRINT_NODE(ctx->dump_ctx, "<invalid block>\n");
return;
}
// 打印基本块标签
static char label_buff[128];
if (bblock->label && bblock->label[0] != '\0') {
scc_snprintf(label_buff, sizeof(label_buff), "%%%s:", bblock->label);
} else {
scc_snprintf(label_buff, sizeof(label_buff), "<unnamed>:");
}
PRINT_NODE(ctx->dump_ctx, label_buff);
// 打印基本块中的每条指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, i);
PRINT_NODE(ctx->dump_ctx, "\n ");
scc_ir_dump_node_linear(ctx, node_ref);
}
}
// 线性输出函数信息
void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx,
scc_ir_func_ref_t func_ref) {
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
static char buff[256];
// 打印函数签名
if (func->name && func->name[0] != '\0') {
scc_snprintf(buff, sizeof(buff), "func @%s", func->name);
} else {
scc_snprintf(buff, sizeof(buff), "func @<unnamed>");
}
PRINT_NODE(ctx->dump_ctx, buff);
// 打印函数参数列表
if (scc_vec_size(func->params) > 0) {
PRINT_NODE(ctx->dump_ctx, "(");
for (usize i = 0; i < scc_vec_size(func->params); i++) {
if (i > 0)
PRINT_NODE(ctx->dump_ctx, ", ");
scc_ir_node_ref_t param_ref = scc_vec_at(func->params, i);
PRINT_NODE(ctx->dump_ctx, "%%");
scc_ir_node_t *param_node =
scc_ir_ctx_get_node(ctx->ir_ctx, param_ref);
if (param_node && param_node->name && param_node->name[0] != '\0') {
scc_snprintf(buff, sizeof(buff), "%u[%s]", param_ref,
param_node->name);
PRINT_NODE(ctx->dump_ctx, buff);
} else {
scc_snprintf(buff, sizeof(buff), "%u", param_ref);
PRINT_NODE(ctx->dump_ctx, buff);
}
}
PRINT_NODE(ctx->dump_ctx, ")");
} else {
PRINT_NODE(ctx->dump_ctx, "()");
}
// 如果有返回类型
if (func->type != 0) {
PRINT_NODE(ctx->dump_ctx, " -> ");
scc_ir_dump_type_linear(ctx, func->type);
}
PRINT_NODE(ctx->dump_ctx, " {\n");
// 打印基本块
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
scc_ir_dump_bblock_linear(ctx, bblock_ref);
PRINT_NODE(ctx->dump_ctx, "\n");
}
PRINT_NODE(ctx->dump_ctx, "}\n");
}
// 线性输出整个程序
void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i));
}
}