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

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

- 在不支持字符的错误信息中添加十六进制编码显示
- 便于调试时识别特殊不可打印字符
2026-02-13 09:56:42 +08:00

826 lines
28 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <ir_ctx.h>
#include <ir_dump.h>
#define PRINT_VALUE(ctx, fmt, value) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->value_color, fmt, value)
#define PRINT_NODE(ctx, name) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", name)
#define PRINT_QUOTED_VALUE(ctx, str) \
SCC_TREE_DUMP_PRINT_AROUND(ctx, ctx->value_color, "'", "%s", str)
// 获取IR节点类型的字符串表示
static const char *get_node_type_str(scc_ir_node_tag_t tag) {
static const char *node_types[] = {
[SCC_IR_NODE_NULL] = "Null", [SCC_IR_NODE_CONST_INT] = "ConstInt",
[SCC_IR_NODE_ALLOC] = "Alloc", [SCC_IR_NODE_LOAD] = "Load",
[SCC_IR_NODE_STORE] = "Store", [SCC_IR_NODE_GET_PTR] = "GetElementPtr",
[SCC_IR_NODE_OP] = "Op", [SCC_IR_NODE_BRANCH] = "Branch",
[SCC_IR_NODE_JUMP] = "Jump", [SCC_IR_NODE_CALL] = "Call",
[SCC_IR_NODE_RET] = "Return",
};
if (tag >= 0 && tag < sizeof(node_types) / sizeof(node_types[0]) &&
node_types[tag] != NULL) {
return node_types[tag];
}
return "UnknownIRNode";
}
// 获取操作符字符串
static const char *get_op_str(scc_ir_op_type_t op) {
static const char *ops[] = {
[IR_OP_EMPTY] = "empty", [IR_OP_NEQ] = "!=", [IR_OP_EQ] = "==",
[IR_OP_GT] = ">", [IR_OP_LT] = "<", [IR_OP_GE] = ">=",
[IR_OP_LE] = "<=", [IR_OP_ADD] = "+", [IR_OP_SUB] = "-",
[IR_OP_MUL] = "*", [IR_OP_DIV] = "/", [IR_OP_MOD] = "%",
[IR_OP_AND] = "&", [IR_OP_OR] = "|", [IR_OP_XOR] = "^",
[IR_OP_NOT] = "~", [IR_OP_SHL] = "<<", [IR_OP_SHR] = ">>",
[IR_OP_SAR] = ">>a", // Arithmetic shift right
};
if (op >= 0 && op < sizeof(ops) / sizeof(ops[0]) && ops[op] != NULL) {
return ops[op];
}
return "<unknown_op>";
}
// 获取类型标签字符串
static const char *get_type_tag_str(scc_ir_type_tag_t tag) {
static const char *type_tags[] = {
[SCC_IR_TYPE_VOID] = "void", [SCC_IR_TYPE_I1] = "i1",
[SCC_IR_TYPE_I8] = "i8", [SCC_IR_TYPE_I16] = "i16",
[SCC_IR_TYPE_I32] = "i32", [SCC_IR_TYPE_I64] = "i64",
[SCC_IR_TYPE_I128] = "i128", [SCC_IR_TYPE_F16] = "f16",
[SCC_IR_TYPE_F32] = "f32", [SCC_IR_TYPE_F64] = "f64",
[SCC_IR_TYPE_F128] = "f128", [SCC_IR_TYPE_PTR] = "ptr",
[SCC_IR_TYPE_ARRAY] = "array", [SCC_IR_TYPE_FUNC] = "func",
[SCC_IR_TYPE_STRUCT] = "struct", [SCC_IR_TYPE_VECTOR] = "vector",
};
if (tag >= 0 && tag < sizeof(type_tags) / sizeof(type_tags[0]) &&
type_tags[tag] != NULL) {
return type_tags[tag];
}
return "<unknown_type>";
}
// 递归转储辅助函数(使用引用)
static inline void dump_child_node_ref(scc_ir_dump_ctx_t *ctx,
scc_ir_node_ref_t child_ref,
cbool is_last) {
if (!child_ref)
return;
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_dump_node(ctx, child_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 转储常量整数节点
static void dump_const_int_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_tree_print_indent(ctx->dump_ctx);
scc_printf("%d\n", node->data.const_int.int32);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 转储操作节点
static void dump_op_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// 打印操作符
scc_tree_dump_push_level(ctx->dump_ctx, false);
scc_tree_print_indent(ctx->dump_ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx->dump_ctx, ctx->dump_ctx->node_color,
"op: %s\n", get_op_str(node->data.op.op));
scc_tree_dump_pop_level(ctx->dump_ctx);
// 左操作数
if (node->data.op.lhs) {
dump_child_node_ref(ctx, node->data.op.lhs,
node->data.op.rhs ? false : true);
}
// 右操作数
if (node->data.op.rhs) {
dump_child_node_ref(ctx, node->data.op.rhs, true);
}
}
// 转储加载节点
static void dump_load_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "load");
if (node->data.load.target) {
dump_child_node_ref(ctx, node->data.load.target, true);
}
}
// 转储存储节点
static void dump_store_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "store");
// 输出存储位置
if (node->data.store.target) {
dump_child_node_ref(ctx, node->data.store.target, false);
}
// 输出存储的值
if (node->data.store.value) {
dump_child_node_ref(ctx, node->data.store.value, true);
}
}
// 转储获取指针节点
static void dump_get_ptr_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "get_ptr");
// 输出源地址
if (node->data.get_ptr.src_addr) {
dump_child_node_ref(ctx, node->data.get_ptr.src_addr, false);
}
// 输出索引
if (node->data.get_ptr.index) {
dump_child_node_ref(ctx, node->data.get_ptr.index, true);
}
}
// 转储分支节点
static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "branch");
// 输出条件
if (node->data.branch.cond) {
dump_child_node_ref(ctx, node->data.branch.cond, false);
}
// 输出真分支块
if (node->data.branch.true_bblock) {
scc_ir_bblock_t *true_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.branch.true_bblock);
if (true_bblock) {
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "TrueBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, true_bblock->label
? true_bblock->label
: "<unnamed>");
}
}
// 输出假分支块
if (node->data.branch.false_bblock) {
scc_ir_bblock_t *false_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.branch.false_bblock);
if (false_bblock) {
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "FalseBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, false_bblock->label
? false_bblock->label
: "<unnamed>");
}
}
}
// 转储跳转节点
static void dump_jump_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "jump");
if (node->data.jump.target_bblock) {
scc_ir_bblock_t *target_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.jump.target_bblock);
if (target_bblock) {
scc_printf("to '%s'", target_bblock->label ? target_bblock->label
: "<unnamed>");
} else {
scc_printf("to invalid block");
}
} else {
scc_printf("to NULL");
}
}
// 转储调用节点
static void dump_call_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "call");
if (node->data.call.callee) {
scc_ir_func_t *callee =
scc_ir_ctx_get_func(ctx->ir_ctx, node->data.call.callee);
if (callee) {
scc_printf("func='%s'", callee->name ? callee->name : "<unnamed>");
} else {
scc_printf("func=<invalid>");
}
} else {
scc_printf("func=NULL");
}
if (scc_vec_size(node->data.call.args) > 0) {
scc_printf("\n");
}
// 输出参数
for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) {
cbool is_last = (i + 1 == scc_vec_size(node->data.call.args));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t arg_ref = scc_vec_at(node->data.call.args, i);
dump_child_node_ref(ctx, arg_ref, is_last);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储返回节点
static void dump_ret_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "ret");
if (node->data.ret.ret_val) {
dump_child_node_ref(ctx, node->data.ret.ret_val, true);
}
}
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) {
LOG_ERROR("Invalid node ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, get_node_type_str(node->tag));
if (node->name && node->name[0]) {
PRINT_VALUE(ctx->dump_ctx, " [%s]", node->name);
}
if (node->type) {
scc_printf(" : ");
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
if (type) {
PRINT_VALUE(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
}
}
scc_printf("\n");
// 根据节点类型输出特定信息
switch (node->tag) {
case SCC_IR_NODE_NULL:
break;
case SCC_IR_NODE_CONST_INT:
dump_const_int_node(ctx, node);
break;
case SCC_IR_NODE_ALLOC:
break;
case SCC_IR_NODE_LOAD:
dump_load_node(ctx, node);
break;
case SCC_IR_NODE_STORE:
dump_store_node(ctx, node);
break;
case SCC_IR_NODE_GET_PTR:
dump_get_ptr_node(ctx, node);
break;
case SCC_IR_NODE_OP:
dump_op_node(ctx, node);
break;
case SCC_IR_NODE_BRANCH:
dump_branch_node(ctx, node);
break;
case SCC_IR_NODE_JUMP:
dump_jump_node(ctx, node);
break;
case SCC_IR_NODE_CALL:
dump_call_node(ctx, node);
break;
case SCC_IR_NODE_RET:
dump_ret_node(ctx, node);
break;
default:
PRINT_QUOTED_VALUE(ctx->dump_ctx, "unknown");
scc_printf("tag(%d)", node->tag);
break;
}
}
// 转储类型信息
void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "Type: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, get_type_tag_str(type->tag));
scc_printf("\n");
// 递归转储子类型
switch (type->tag) {
case SCC_IR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.pointer.base);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_print_indent(ctx->dump_ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx->dump_ctx, ctx->dump_ctx->node_color,
"Array Length: %zu\n",
type->data.array.len);
}
if (type->data.array.base) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.array.base);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_FUNC:
// 先输出参数类型
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_type_ref_t param_type_ref =
scc_vec_at(type->data.function.params, i);
scc_ir_dump_type(ctx, param_type_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 再输出返回类型
if (type->data.function.ret_type) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.function.ret_type);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_STRUCT:
// 结构体处理
break;
case SCC_IR_TYPE_VECTOR:
// 向量处理
break;
default:
break;
}
}
// 转储基本块
void scc_ir_dump_bblock(scc_ir_dump_ctx_t *ctx,
scc_ir_bblock_ref_t bblock_ref) {
if (!ctx || !bblock_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_ir_bblock_t *bblock = scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref);
if (!bblock) {
LOG_ERROR("invalid bblock ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "BasicBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx,
bblock->label ? bblock->label : "<unnamed>");
scc_printf("\n");
// 转储基本块中的指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
cbool is_last = (i + 1 == scc_vec_size(bblock->instrs));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t instr_ref = scc_vec_at(bblock->instrs, i);
scc_ir_dump_node(ctx, instr_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储函数
void scc_ir_dump_func(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 (!ctx || !func) {
LOG_ERROR("invalid parameter");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "Function: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, func->name ? func->name : "<unnamed>");
scc_printf("\n");
// 输出函数类型
if (func->type) {
scc_tree_dump_push_level(ctx->dump_ctx, false);
scc_ir_dump_type(ctx, func->type);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 输出函数参数
for (usize i = 0; i < scc_vec_size(func->params); i++) {
cbool is_last = (i + 1 == scc_vec_size(func->params));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t param_ref = scc_vec_at(func->params, i);
scc_ir_dump_node(ctx, param_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 输出基本块
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
cbool is_last = (i + 1 == scc_vec_size(func->bblocks));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
scc_ir_dump_bblock(ctx, bblock_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储整个程序
void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx) {
// 输出全局值
// if (scc_vec_size(program->global_vals) > 0) {
// print_indented(ctx, "Global Values:", "");
// for (usize i = 0; i < scc_vec_size(program->global_vals); i++) {
// cbool is_last = (i + 1 ==
// scc_vec_size(program->global_vals));
// scc_tree_dump_push_level(ctx->dump_ctx, is_last);
// scc_ir_node_ref_t global_ref =
// scc_vec_at(program->global_vals, i); scc_ir_node_t
// *global_node =
// scc_ir_ctx_get_node(ir_ctx, global_ref);
// if (global_node) {
// scc_ir_dump_node(ctx, ir_ctx, global_node);
// }
// scc_tree_dump_pop_level(ctx->dump_ctx);
// }
// }
// // 输出函数定义
// if (scc_vec_size(ir_ctx->funcs) > 0) {
// print_indented(ctx, "Functions:", "");
// for (usize i = 0; i < scc_vec_size(ir_ctx->funcs); i++) {
// cbool is_last = (i + 1 == scc_vec_size(ir_ctx->funcs));
// scc_tree_dump_push_level(ctx->dump_ctx, is_last);
// scc_ir_func_t func_ref = scc_vec_at(ir_ctx->funcs, i);
// if (func_ref.type != 0) {
// // TODO hack it
// dump_func_ref(ir_ctx, ctx, i + 1);
// }
// scc_tree_dump_pop_level(ctx->dump_ctx);
// }
// }
PRINT_NODE(ctx->dump_ctx, "Func defs:\n");
scc_vec_foreach(ctx->cprog->func_defs, i) {
cbool is_last = (i + 1 == scc_vec_size(ctx->cprog->func_defs));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_dump_func(ctx, scc_vec_at(ctx->cprog->func_defs, i));
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));
}
}