feat(ir): 添加线性IR转储功能并改进AST转储
- 实现了IR的线性转储功能,包括类型、节点、基本块和函数的线性表示 - 添加了scc_ir_dump_ctx_init函数用于初始化转储上下文 - 为AST函数类型添加了变参标记注释说明 - 改进了AST转储中函数类型的参数和返回值显示逻辑 - 统一了AST解析中节点类型的声明为通用的scc_ast_node_t指针类型 fix(lexer): 改进词法分析器错误信息显示 - 在不支持字符的错误信息中添加十六进制编码显示 - 便于调试时识别特殊不可打印字符
This commit is contained in:
@@ -162,7 +162,7 @@ struct scc_ast_type {
|
|||||||
struct {
|
struct {
|
||||||
scc_ast_type_t *return_type;
|
scc_ast_type_t *return_type;
|
||||||
scc_ast_type_vec_t param_types;
|
scc_ast_type_vec_t param_types;
|
||||||
cbool is_variadic;
|
cbool is_variadic; // va_arg <=> ...
|
||||||
} function;
|
} function;
|
||||||
struct {
|
struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|||||||
@@ -315,6 +315,19 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
|
|||||||
break;
|
break;
|
||||||
case SCC_AST_TYPE_FUNCTION:
|
case SCC_AST_TYPE_FUNCTION:
|
||||||
PRINT_QUOTED_VALUE(ctx, "function");
|
PRINT_QUOTED_VALUE(ctx, "function");
|
||||||
|
scc_printf("\n");
|
||||||
|
if (type->function.return_type) {
|
||||||
|
dump_type_impl(type->function.return_type, ctx);
|
||||||
|
}
|
||||||
|
if (scc_vec_size(type->function.param_types) != 0) {
|
||||||
|
scc_vec_foreach(type->function.param_types, i) {
|
||||||
|
dump_type_impl(scc_vec_at(type->function.param_types, i), ctx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start_node_dump(&type->base, ctx);
|
||||||
|
PRINT_QUOTED_VALUE(ctx, "void");
|
||||||
|
// TODO?
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_AST_TYPE_STRUCT:
|
case SCC_AST_TYPE_STRUCT:
|
||||||
if (type->record.name) {
|
if (type->record.name) {
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ typedef struct {
|
|||||||
scc_ir_cprog_t *cprog;
|
scc_ir_cprog_t *cprog;
|
||||||
scc_tree_dump_ctx_t *dump_ctx;
|
scc_tree_dump_ctx_t *dump_ctx;
|
||||||
} scc_ir_dump_ctx_t;
|
} scc_ir_dump_ctx_t;
|
||||||
void scc_ir_dump_ctx_init();
|
|
||||||
|
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);
|
||||||
|
|
||||||
void scc_ir_dump_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref);
|
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);
|
void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref);
|
||||||
@@ -18,4 +21,6 @@ void scc_ir_dump_bblock(scc_ir_dump_ctx_t *ctx, scc_ir_bblock_ref_t bblock_ref);
|
|||||||
void scc_ir_dump_func(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref);
|
void scc_ir_dump_func(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref);
|
||||||
void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx);
|
void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx);
|
||||||
|
|
||||||
|
void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx);
|
||||||
|
|
||||||
#endif /* __SCC_IR_DUMP_H__ */
|
#endif /* __SCC_IR_DUMP_H__ */
|
||||||
|
|||||||
@@ -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) {
|
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);
|
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
|
||||||
if (!node) {
|
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) {
|
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) {
|
if (!ctx || !type_ref) {
|
||||||
LOG_ERROR("invalid parameter");
|
LOG_ERROR("invalid parameter");
|
||||||
return;
|
return;
|
||||||
@@ -520,3 +502,324 @@ void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx) {
|
|||||||
scc_tree_dump_pop_level(ctx->dump_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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
token->type = type;
|
token->type = type;
|
||||||
goto END;
|
goto END;
|
||||||
default:
|
default:
|
||||||
LEX_ERROR("unsupport char in sourse code `%c`", ch);
|
LEX_ERROR("unsupport char in sourse code `%c`:0x%x", ch, ch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
goto once_char;
|
goto once_char;
|
||||||
|
|||||||
@@ -158,10 +158,10 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
|
|||||||
while (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_BRACE)) {
|
while (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_BRACE)) {
|
||||||
/// TODO
|
/// TODO
|
||||||
// scc_parse_is_decl();
|
// scc_parse_is_decl();
|
||||||
scc_ast_node_type_t *ret = null;
|
scc_ast_node_t *ret = null;
|
||||||
ret = (scc_ast_node_type_t *)scc_parse_declaration(parser);
|
ret = (scc_ast_node_t *)scc_parse_declaration(parser);
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
ret = (scc_ast_node_type_t *)scc_parse_statement(parser);
|
ret = (scc_ast_node_t *)scc_parse_statement(parser);
|
||||||
}
|
}
|
||||||
if (ret == null) {
|
if (ret == null) {
|
||||||
LOG_ERROR("Invalid statement");
|
LOG_ERROR("Invalid statement");
|
||||||
|
|||||||
Reference in New Issue
Block a user