Files
scc/libs/ir/hir/src/hir_dump.c
zzy 0fbfb36262 feat(cbuild): 更新项目配置以支持HIR中间表示
- 统一包名格式化,添加空格对齐
- 将依赖项从ir和lir重命名为hir,移除lir注释
- 为ast2ir模块添加正确的包名称"scc_ast2ir"
- 更新依赖引用路径指向新的HIR库结构
- 移除注释掉的ir2mcode和sccf2target依赖项

refactor(ast2ir): 迁移到HIR中间表示替换IR表示

- 更新头文件包含,使用hir_builder.h替代ir_builder.h
- 修改上下文结构体,将scc_ir_builder_t替换为scc_hir_builder_t
- 更新函数签名,将参数类型从scc_ir_*转换为scc_hir_*
- 调整返回值类型,将scc_ir_value_ref_t和scc_ir_type_ref_t
  分别替换为scc_hir_value_ref_t和scc_hir_type_ref_t
- 重新排列头文件包含顺序以满足依赖关系
2026-04-21 14:05:21 +08:00

708 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 <hir_dump.h>
#include <hir_prog.h>
#include <scc_tree_dump.h>
#define GET_MODULE(ctx) (&(ctx->cprog->module))
static const char *get_node_type_str(scc_hir_value_tag_t tag) {
static const char *node_types[] = {
[SCC_HIR_VALUE_TAG_NULLPTR] = "NullPtr",
[SCC_HIR_VALUE_TAG_BUILTIN] = "Builtin",
[SCC_HIR_VALUE_TAG_INTEGER] = "ConstInt",
[SCC_HIR_VALUE_TAG_DECIMAL] = "ConstFloat",
[SCC_HIR_VALUE_TAG_ARRAY] = "ConstArray",
[SCC_HIR_VALUE_TAG_AGGREGATE] = "Aggregate",
[SCC_HIR_VALUE_TAG_CONV] = "Convert",
[SCC_HIR_VALUE_TAG_FUNC_ARG_REF] = "FuncArgRef",
[SCC_HIR_VALUE_TAG_BLOCK_ARG_REF] = "BlockArgRef",
[SCC_HIR_VALUE_TAG_ALLOC] = "Alloc",
[SCC_HIR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc",
[SCC_HIR_VALUE_TAG_LOAD] = "Load",
[SCC_HIR_VALUE_TAG_STORE] = "Store",
[SCC_HIR_VALUE_TAG_GET_ELEM_PTR] = "GetElemPtr",
[SCC_HIR_VALUE_TAG_OP] = "Op",
[SCC_HIR_VALUE_TAG_BRANCH] = "Branch",
[SCC_HIR_VALUE_TAG_JUMP] = "Jump",
[SCC_HIR_VALUE_TAG_CALL] = "Call",
[SCC_HIR_VALUE_TAG_RET] = "Ret",
};
if (tag >= 0 && (usize)tag < sizeof(node_types) / sizeof(node_types[0]) &&
node_types[tag])
return node_types[tag];
return "UnknownIRNode";
}
static const char *get_op_str(scc_hir_op_type_t op) {
static const char *ops[] = {
[SCC_HIR_OP_EMPTY] = "empty", [SCC_HIR_OP_NEQ] = "!=",
[SCC_HIR_OP_EQ] = "==", [SCC_HIR_OP_GT] = ">",
[SCC_HIR_OP_LT] = "<", [SCC_HIR_OP_GE] = ">=",
[SCC_HIR_OP_LE] = "<=", [SCC_HIR_OP_ADD] = "+",
[SCC_HIR_OP_SUB] = "-", [SCC_HIR_OP_MUL] = "*",
[SCC_HIR_OP_DIV] = "/", [SCC_HIR_OP_MOD] = "%",
[SCC_HIR_OP_AND] = "&", [SCC_HIR_OP_OR] = "|",
[SCC_HIR_OP_XOR] = "^", [SCC_HIR_OP_NOT] = "~",
[SCC_HIR_OP_SHL] = "<<", [SCC_HIR_OP_SHR] = ">>",
[SCC_HIR_OP_SAR] = ">>a",
};
if (op >= 0 && (usize)op < sizeof(ops) / sizeof(ops[0]) && ops[op])
return ops[op];
return "<unknown_op>";
}
static const char *get_type_tag_str(scc_hir_type_tag_t tag) {
static const char *type_tags[] = {
[SCC_HIR_TYPE_void] = "void", [SCC_HIR_TYPE_u8] = "u8",
[SCC_HIR_TYPE_u16] = "u16", [SCC_HIR_TYPE_u32] = "u32",
[SCC_HIR_TYPE_u64] = "u64", [SCC_HIR_TYPE_u128] = "u128",
[SCC_HIR_TYPE_i8] = "i8", [SCC_HIR_TYPE_i16] = "i16",
[SCC_HIR_TYPE_i32] = "i32", [SCC_HIR_TYPE_i64] = "i64",
[SCC_HIR_TYPE_i128] = "i128", [SCC_HIR_TYPE_f16] = "f16",
[SCC_HIR_TYPE_f32] = "f32", [SCC_HIR_TYPE_f64] = "f64",
[SCC_HIR_TYPE_f128] = "f128", [SCC_HIR_TYPE_PTR] = "ptr",
[SCC_HIR_TYPE_ARRAY] = "array", [SCC_HIR_TYPE_FUNC] = "func",
[SCC_HIR_TYPE_STRUCT] = "struct", [SCC_HIR_TYPE_VECTOR] = "vector",
};
if (tag >= 0 && (usize)tag < sizeof(type_tags) / sizeof(type_tags[0]) &&
type_tags[tag])
return type_tags[tag];
return "<unknown_type>";
}
static inline void dump_child_node_ref(scc_hir_dump_t *ctx,
scc_hir_value_ref_t child,
cbool is_last) {
if (!child)
return;
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_dump_value(ctx, child);
scc_tree_dump_pop(ctx->dump_ctx);
}
static void dump_integer_node(scc_hir_dump_t *ctx,
const scc_hir_value_t *value) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_tree_dump_begin_line(ctx->dump_ctx);
// FIXME hack it
scc_tree_dump_value(ctx->dump_ctx, "%d", value->data.integer.data.digit);
scc_tree_dump_pop(ctx->dump_ctx);
}
static void dump_op_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
scc_tree_dump_push(ctx->dump_ctx, false);
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "op: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_op_str(value->data.op.op));
scc_tree_dump_pop(ctx->dump_ctx);
if (value->data.op.lhs)
dump_child_node_ref(ctx, value->data.op.lhs,
value->data.op.rhs ? false : true);
if (value->data.op.rhs)
dump_child_node_ref(ctx, value->data.op.rhs, true);
}
static void dump_load_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
if (value->data.load.target)
dump_child_node_ref(ctx, value->data.load.target, true);
}
static void dump_store_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
if (value->data.store.target)
dump_child_node_ref(ctx, value->data.store.target, false);
if (value->data.store.value)
dump_child_node_ref(ctx, value->data.store.value, true);
}
static void dump_get_elem_ptr_node(scc_hir_dump_t *ctx,
const scc_hir_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_hir_dump_t *ctx,
const scc_hir_value_t *value) {
if (value->data.branch.cond)
dump_child_node_ref(ctx, value->data.branch.cond, false);
if (value->data.branch.true_bblock) {
scc_hir_bblock_t *true_bblock = scc_hir_module_get_bblock(
GET_MODULE(ctx), value->data.branch.true_bblock);
if (true_bblock) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "TrueBlock: ");
scc_tree_dump_value(ctx->dump_ctx, "'%s'",
true_bblock->name ? true_bblock->name
: "<unnamed>");
}
}
if (value->data.branch.false_bblock) {
scc_hir_bblock_t *false_bblock = scc_hir_module_get_bblock(
GET_MODULE(ctx), value->data.branch.false_bblock);
if (false_bblock) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "FalseBlock: ");
scc_tree_dump_value(ctx->dump_ctx, "'%s'",
false_bblock->name ? false_bblock->name
: "<unnamed>");
}
}
}
static void dump_jump_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
scc_tree_dump_begin_line(ctx->dump_ctx);
if (value->data.jump.target_bblock) {
scc_hir_bblock_t *target = scc_hir_module_get_bblock(
GET_MODULE(ctx), value->data.jump.target_bblock);
if (target)
scc_tree_dump_value(ctx->dump_ctx, "to '%s'",
target->name ? target->name : "<unnamed>");
else
scc_tree_dump_value(ctx->dump_ctx, "to invalid block");
} else {
scc_tree_dump_value(ctx->dump_ctx, "to nullptr");
}
}
static void dump_call_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
scc_tree_dump_begin_line(ctx->dump_ctx);
if (value->data.call.callee) {
scc_hir_func_t *callee =
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
scc_tree_dump_value(ctx->dump_ctx, "func='%s'",
callee ? (callee->name ? callee->name : "<unnamed>")
: "<invalid>");
} else {
scc_tree_dump_value(ctx->dump_ctx, "func=nullptr");
}
for (usize i = 0; i < scc_vec_size(value->data.call.args); i++) {
cbool is_last = (i + 1 == scc_vec_size(value->data.call.args));
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_value_ref_t arg = scc_vec_at(value->data.call.args, i);
dump_child_node_ref(ctx, arg, is_last);
scc_tree_dump_pop(ctx->dump_ctx);
}
}
static void dump_ret_node(scc_hir_dump_t *ctx, const scc_hir_value_t *value) {
if (value->data.ret.ret_val)
dump_child_node_ref(ctx, value->data.ret.ret_val, true);
}
void scc_hir_dump_ctx_init(scc_hir_dump_t *ctx, scc_tree_dump_t *td,
scc_hir_cprog_t *cprog) {
ctx->cprog = cprog;
ctx->dump_ctx = td;
}
void scc_hir_dump_value(scc_hir_dump_t *ctx, scc_hir_value_ref_t value_ref) {
scc_hir_value_t *value =
scc_hir_module_get_value(GET_MODULE(ctx), value_ref);
if (!value) {
LOG_ERROR("Invalid value ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "%s", get_node_type_str(value->tag));
if (value->name && value->name[0])
scc_tree_dump_value(ctx->dump_ctx, " [%s]", value->name);
if (value->type) {
scc_hir_type_t *type =
scc_hir_module_get_type(GET_MODULE(ctx), value->type);
if (type) {
scc_tree_dump_append(ctx->dump_ctx, " : ");
scc_tree_dump_value(ctx->dump_ctx, "%s",
get_type_tag_str(type->tag));
}
}
switch (value->tag) {
case SCC_HIR_VALUE_TAG_INTEGER:
dump_integer_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_ALLOC:
break;
case SCC_HIR_VALUE_TAG_LOAD:
dump_load_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_STORE:
dump_store_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR:
dump_get_elem_ptr_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_OP:
dump_op_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_BRANCH:
dump_branch_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_JUMP:
dump_jump_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_CALL:
dump_call_node(ctx, value);
break;
case SCC_HIR_VALUE_TAG_RET:
dump_ret_node(ctx, value);
break;
default:
scc_tree_dump_value(ctx->dump_ctx, "unknown");
scc_tree_dump_append_fmt(ctx->dump_ctx, " tag(%d)", value->tag);
break;
}
}
void scc_hir_dump_type(scc_hir_dump_t *ctx, scc_hir_type_ref_t type_ref) {
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Type: ");
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
switch (type->tag) {
case SCC_HIR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.pointer.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Array Length: ");
scc_tree_dump_value(ctx->dump_ctx, "%zu", type->data.array.len);
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
if (type->data.array.base) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.array.base);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
case SCC_HIR_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(ctx->dump_ctx, is_last);
scc_hir_dump_type(ctx, scc_vec_at(type->data.function.params, i));
scc_tree_dump_pop(ctx->dump_ctx);
}
if (type->data.function.ret_type) {
scc_tree_dump_push(ctx->dump_ctx, true);
scc_hir_dump_type(ctx, type->data.function.ret_type);
scc_tree_dump_pop(ctx->dump_ctx);
}
break;
default:
break;
}
}
void scc_hir_dump_bblock(scc_hir_dump_t *ctx, scc_hir_bblock_ref_t bblock_ref) {
if (!ctx || !bblock_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_hir_bblock_t *bblock =
scc_hir_module_get_bblock(GET_MODULE(ctx), bblock_ref);
if (!bblock) {
LOG_ERROR("invalid bblock ref");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "BasicBlock: ");
scc_tree_dump_value(ctx->dump_ctx, "'%s'",
bblock->name ? bblock->name : "<unnamed>");
scc_tree_dump_append(ctx->dump_ctx, "\n");
for (usize i = 0; i < scc_vec_size(SCC_HIR_BBLOCK_VALUES(*bblock)); i++) {
cbool is_last = (i + 1 == scc_vec_size(SCC_HIR_BBLOCK_VALUES(*bblock)));
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_dump_value(ctx, scc_vec_at(SCC_HIR_BBLOCK_VALUES(*bblock), i));
scc_tree_dump_pop(ctx->dump_ctx);
}
}
void scc_hir_dump_func(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref) {
scc_hir_func_t *func = scc_hir_module_get_func(GET_MODULE(ctx), func_ref);
if (!ctx || !func) {
LOG_ERROR("invalid parameter");
return;
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_node(ctx->dump_ctx, "Function: ");
scc_tree_dump_value(ctx->dump_ctx, "'%s'",
func->name ? func->name : "<unnamed>");
scc_tree_dump_append(ctx->dump_ctx, "\n");
if (SCC_HIR_FUNC_META(*func)->type) {
scc_tree_dump_push(ctx->dump_ctx, false);
scc_hir_dump_type(ctx, SCC_HIR_FUNC_META(*func)->type);
scc_tree_dump_pop(ctx->dump_ctx);
}
for (usize i = 0; i < scc_vec_size(SCC_HIR_FUNC_META(*func)->params); i++) {
cbool is_last =
(i + 1 == scc_vec_size(SCC_HIR_FUNC_META(*func)->params));
scc_tree_dump_push(ctx->dump_ctx, is_last);
scc_hir_dump_value(ctx,
scc_vec_at(SCC_HIR_FUNC_META(*func)->params, i));
scc_tree_dump_pop(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(ctx->dump_ctx, is_last);
scc_hir_dump_bblock(ctx, scc_vec_at(func->bblocks, i));
scc_tree_dump_pop(ctx->dump_ctx);
}
}
void scc_hir_dump_cprog(scc_hir_dump_t *ctx) {
scc_tree_dump_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(ctx->dump_ctx, is_last);
scc_hir_dump_func(ctx, scc_vec_at(ctx->cprog->func_defs, i));
scc_tree_dump_pop(ctx->dump_ctx);
}
}
// ----- 线性输出(保留原逻辑,改用新 API-----
void scc_hir_dump_type_linear(scc_hir_dump_t *ctx,
scc_hir_type_ref_t type_ref) {
scc_hir_type_t *type = scc_hir_module_get_type(GET_MODULE(ctx), type_ref);
if (!ctx || !type) {
LOG_ERROR("invalid parameter");
return;
}
switch (type->tag) {
case SCC_HIR_TYPE_unknown:
case SCC_HIR_TYPE_void:
case SCC_HIR_TYPE_i8:
case SCC_HIR_TYPE_i16:
case SCC_HIR_TYPE_i32:
case SCC_HIR_TYPE_i64:
case SCC_HIR_TYPE_i128:
case SCC_HIR_TYPE_u8:
case SCC_HIR_TYPE_u16:
case SCC_HIR_TYPE_u32:
case SCC_HIR_TYPE_u64:
case SCC_HIR_TYPE_u128:
case SCC_HIR_TYPE_f16:
case SCC_HIR_TYPE_f32:
case SCC_HIR_TYPE_f64:
case SCC_HIR_TYPE_f128:
scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
break;
case SCC_HIR_TYPE_ARRAY:
scc_tree_dump_append(ctx->dump_ctx, "[");
scc_hir_dump_type_linear(ctx, type->data.array.base);
scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len);
break;
case SCC_HIR_TYPE_PTR:
scc_tree_dump_append(ctx->dump_ctx, "*");
scc_hir_dump_type_linear(ctx, type->data.pointer.base);
break;
case SCC_HIR_TYPE_FUNC:
scc_tree_dump_append(ctx->dump_ctx, "(");
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
if (i > 0)
scc_tree_dump_append(ctx->dump_ctx, ", ");
scc_hir_dump_type_linear(ctx,
scc_vec_at(type->data.function.params, i));
}
if (type->data.function.ret_type) {
scc_tree_dump_append(ctx->dump_ctx, ") -> ");
scc_hir_dump_type_linear(ctx, type->data.function.ret_type);
} else {
scc_tree_dump_append(ctx->dump_ctx, ")");
}
break;
default:
LOG_ERROR("invalid type tag");
break;
}
}
static void format_ref_or_value(scc_hir_dump_t *ctx,
scc_hir_value_ref_t value_ref) {
scc_hir_value_t *value =
scc_hir_module_get_value(GET_MODULE(ctx), value_ref);
if (!value) {
scc_tree_dump_append_fmt(ctx->dump_ctx, "%%%u", value_ref);
return;
}
// FIXME
// if (value->tag == SCC_HIR_VALUE_TAG_INTEGER) {
// scc_tree_dump_append_fmt(ctx->dump_ctx, "%d",
// value->data.const_int.int32);
// return;
// }
if (value->name && value->name[0] != '\0') {
scc_tree_dump_node(ctx->dump_ctx, "%%%u[%s]", value_ref, value->name);
} else {
scc_tree_dump_node(ctx->dump_ctx, "%%%u", value_ref);
}
if (value->type != SCC_HIR_REF_nullptr) {
scc_tree_dump_append(ctx->dump_ctx, ":");
scc_hir_dump_type_linear(ctx, value->type);
}
}
void scc_hir_dump_value_linear(scc_hir_dump_t *ctx,
scc_hir_value_ref_t value_ref) {
scc_hir_value_t *value =
scc_hir_module_get_value(GET_MODULE(ctx), value_ref);
if (!value) {
scc_tree_dump_append(ctx->dump_ctx, "<invalid value>\n");
return;
}
cbool needs_equals = (value->tag != SCC_HIR_VALUE_TAG_BRANCH &&
value->tag != SCC_HIR_VALUE_TAG_JUMP &&
value->tag != SCC_HIR_VALUE_TAG_RET &&
value->tag != SCC_HIR_VALUE_TAG_STORE);
if (needs_equals) {
format_ref_or_value(ctx, value_ref);
scc_tree_dump_append(ctx->dump_ctx, " = ");
}
switch (value->tag) {
case SCC_HIR_VALUE_TAG_BUILTIN: {
scc_tree_dump_append(ctx->dump_ctx, "@scc::");
switch (value->data.builtin.tag) {
case SCC_HIR_BUILTIN_TAG_MEMCPY:
scc_tree_dump_append(ctx->dump_ctx, "memcpy");
scc_tree_dump_append(ctx->dump_ctx, "(");
format_ref_or_value(ctx, value->data.builtin.func.memcpy.dest);
scc_tree_dump_append(ctx->dump_ctx, ", ");
format_ref_or_value(ctx, value->data.builtin.func.memcpy.src);
scc_tree_dump_append(ctx->dump_ctx, ", ");
format_ref_or_value(ctx, value->data.builtin.func.memcpy.size);
scc_tree_dump_append(ctx->dump_ctx, ")");
break;
case SCC_HIR_BUILTIN_TAG_MEMSET:
scc_tree_dump_append(ctx->dump_ctx, "memset");
break;
case SCC_HIR_BUILTIN_TAG_VA_ARG:
scc_tree_dump_append(ctx->dump_ctx, "va_arg");
break;
case SCC_HIR_BUILTIN_TAG_VA_END:
scc_tree_dump_append(ctx->dump_ctx, "va_end");
break;
case SCC_HIR_BUILTIN_TAG_VA_COPY:
scc_tree_dump_append(ctx->dump_ctx, "va_copy");
break;
case SCC_HIR_BUILTIN_TAG_VA_START:
scc_tree_dump_append(ctx->dump_ctx, "va_start");
break;
default:
Panic("Unknown builtin tag");
break;
}
break;
}
case SCC_HIR_VALUE_TAG_INTEGER:
// 值已经在 format 中输出,这里不需要再做
break;
case SCC_HIR_VALUE_TAG_AGGREGATE:
// 聚合类型:递归输出每个元素(每个占一行)
scc_vec_foreach(value->data.aggregate.fields, i) {
scc_hir_dump_value_linear(
ctx, scc_vec_at(value->data.aggregate.fields, i));
scc_tree_dump_append(ctx->dump_ctx, "\n");
}
return;
case SCC_HIR_VALUE_TAG_ALLOC:
scc_tree_dump_append(ctx->dump_ctx, "alloc");
break;
case SCC_HIR_VALUE_TAG_LOAD:
scc_tree_dump_append(ctx->dump_ctx, "load ");
format_ref_or_value(ctx, value->data.load.target);
break;
case SCC_HIR_VALUE_TAG_STORE:
scc_tree_dump_append(ctx->dump_ctx, "store ");
format_ref_or_value(ctx, value->data.store.value);
scc_tree_dump_append(ctx->dump_ctx, " -> ");
format_ref_or_value(ctx, value->data.store.target);
break;
case SCC_HIR_VALUE_TAG_GET_ELEM_PTR:
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_elem_ptr.index);
break;
case SCC_HIR_VALUE_TAG_OP:
format_ref_or_value(ctx, value->data.op.lhs);
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s ",
get_op_str(value->data.op.op));
format_ref_or_value(ctx, value->data.op.rhs);
break;
case SCC_HIR_VALUE_TAG_BRANCH:
if (value->data.branch.cond) {
scc_tree_dump_append(ctx->dump_ctx, "br ");
format_ref_or_value(ctx, value->data.branch.cond);
scc_tree_dump_append_fmt(ctx->dump_ctx,
", label %%L%u, label %%L%u",
value->data.branch.true_bblock,
value->data.branch.false_bblock);
} else {
scc_tree_dump_append_fmt(ctx->dump_ctx, "br label %%L%u",
value->data.branch.true_bblock);
}
break;
case SCC_HIR_VALUE_TAG_JUMP:
scc_tree_dump_append_fmt(ctx->dump_ctx, "jmp label %%L%u",
value->data.jump.target_bblock);
break;
case SCC_HIR_VALUE_TAG_CALL: {
scc_hir_func_t *func =
scc_hir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(",
func ? (func->name ? func->name : "<unnamed>")
: "<invalid>");
for (usize i = 0; i < scc_vec_size(value->data.call.args); i++) {
if (i > 0)
scc_tree_dump_append(ctx->dump_ctx, ", ");
format_ref_or_value(ctx, scc_vec_at(value->data.call.args, i));
}
scc_tree_dump_append(ctx->dump_ctx, ")");
break;
}
case SCC_HIR_VALUE_TAG_RET:
if (value->data.ret.ret_val != 0) {
scc_tree_dump_append(ctx->dump_ctx, "ret ");
format_ref_or_value(ctx, value->data.ret.ret_val);
} else {
scc_tree_dump_append(ctx->dump_ctx, "ret void");
}
break;
case SCC_HIR_VALUE_TAG_FUNC_ARG_REF:
scc_tree_dump_append_fmt(ctx->dump_ctx, "arg[%zu]",
value->data.arg_ref.idx);
break;
case SCC_HIR_VALUE_TAG_GLOBAL_ALLOC:
scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s", value->name);
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_hir_dump_value_linear(ctx, value->data.global_alloc.value);
return;
case SCC_HIR_VALUE_TAG_ARRAY:
scc_tree_dump_append(ctx->dump_ctx, "const_array ");
scc_hir_dump_type_linear(ctx, value->data.const_array.base_type);
scc_tree_dump_append(ctx->dump_ctx, " [");
scc_vec_foreach(value->data.const_array.fields, i) {
u8 ch = scc_vec_at(value->data.const_array.fields, i);
scc_tree_dump_append_fmt(ctx->dump_ctx, " `%c`, ", ch ? ch : ' ');
}
scc_tree_dump_append(ctx->dump_ctx, " ]");
break;
default:
scc_tree_dump_append_fmt(ctx->dump_ctx, "<%s value %u>",
get_node_type_str(value->tag), value_ref);
break;
}
}
void scc_hir_dump_bblock_linear(scc_hir_dump_t *ctx,
scc_hir_bblock_ref_t bblock_ref) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_hir_bblock_t *bblock =
scc_hir_module_get_bblock(GET_MODULE(ctx), bblock_ref);
if (!bblock) {
scc_tree_dump_append(ctx->dump_ctx, "<invalid block>");
return;
}
if (bblock->name && bblock->name[0] != '\0')
scc_tree_dump_append_fmt(ctx->dump_ctx, "%%L%d %s:", bblock_ref,
bblock->name);
else
scc_tree_dump_append_fmt(ctx->dump_ctx, "%%L%d <unnamed>:", bblock_ref);
for (usize i = 0; i < scc_vec_size(SCC_HIR_BBLOCK_VALUES(*bblock)); i++) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_append(ctx->dump_ctx, " ");
scc_hir_dump_value_linear(
ctx, scc_vec_at(SCC_HIR_BBLOCK_VALUES(*bblock), i));
}
}
void scc_hir_dump_func_linear(scc_hir_dump_t *ctx, scc_hir_func_ref_t func_ref,
int is_decl) {
scc_hir_func_t *func = scc_hir_module_get_func(GET_MODULE(ctx), func_ref);
scc_tree_dump_begin_line(ctx->dump_ctx);
if (!func) {
scc_tree_dump_append(ctx->dump_ctx, "<invalid function>");
return;
}
scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s",
(func->name && func->name[0]) ? func->name
: "<unnamed>");
if (scc_vec_size(SCC_HIR_FUNC_META(*func)->params) > 0) {
scc_tree_dump_append(ctx->dump_ctx, "(");
for (usize i = 0; i < scc_vec_size(SCC_HIR_FUNC_META(*func)->params);
i++) {
if (i > 0)
scc_tree_dump_append(ctx->dump_ctx, ", ");
scc_hir_value_ref_t param_ref =
scc_vec_at(SCC_HIR_FUNC_META(*func)->params, i);
scc_hir_value_t *param_node =
scc_hir_module_get_value(GET_MODULE(ctx), param_ref);
scc_tree_dump_append(ctx->dump_ctx, "%");
if (param_node && param_node->name && param_node->name[0] != '\0')
scc_tree_dump_append_fmt(ctx->dump_ctx, "%u[%s]", param_ref,
param_node->name);
else
scc_tree_dump_append_fmt(ctx->dump_ctx, "%u", param_ref);
}
scc_tree_dump_append(ctx->dump_ctx, ")");
} else {
scc_tree_dump_append(ctx->dump_ctx, "()");
}
scc_tree_dump_append(ctx->dump_ctx, ": ");
scc_hir_dump_type_linear(ctx, SCC_HIR_FUNC_META(*func)->type);
if (is_decl) {
scc_tree_dump_append(ctx->dump_ctx, ";");
return;
}
scc_tree_dump_append(ctx->dump_ctx, " {");
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
scc_hir_dump_bblock_linear(ctx, scc_vec_at(func->bblocks, i));
scc_tree_dump_append(ctx->dump_ctx, "");
}
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_tree_dump_append(ctx->dump_ctx, "}");
}
void scc_hir_dump_cprog_linear(scc_hir_dump_t *ctx) {
for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) {
scc_tree_dump_begin_line(ctx->dump_ctx);
scc_hir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i));
}
for (usize i = 0; i < scc_vec_size(ctx->cprog->func_decls); i++) {
scc_hir_func_ref_t func_decl = scc_vec_at(ctx->cprog->func_decls, i);
scc_hir_func_t *func =
scc_hir_module_get_func(GET_MODULE(ctx), func_decl);
if (func && scc_vec_size(func->bblocks) == 0)
scc_hir_dump_func_linear(ctx, func_decl, 1);
}
for (usize i = 0; i < scc_vec_size(ctx->cprog->func_defs); i++) {
scc_hir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i), 0);
}
}