#include #include #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 ""; } // 获取类型标签字符串 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 ""; } // 递归转储辅助函数(使用引用) 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 : ""); } } // 输出假分支块 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 : ""); } } } // 转储跳转节点 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 : ""); } 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 : ""); } else { scc_printf("func="); } } 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 : ""); 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 : ""); 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, "\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), ":"); } 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 @"); } 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)); } }