diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index fe861a5..e06a503 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -162,7 +162,7 @@ struct scc_ast_type { struct { scc_ast_type_t *return_type; scc_ast_type_vec_t param_types; - cbool is_variadic; + cbool is_variadic; // va_arg <=> ... } function; struct { const char *name; diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 702d935..c46f77a 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -315,6 +315,19 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { break; case SCC_AST_TYPE_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; case SCC_AST_TYPE_STRUCT: if (type->record.name) { diff --git a/libs/ir/include/ir_dump.h b/libs/ir/include/ir_dump.h index 08f2881..4bf70b5 100644 --- a/libs/ir/include/ir_dump.h +++ b/libs/ir/include/ir_dump.h @@ -10,7 +10,10 @@ typedef struct { scc_ir_cprog_t *cprog; scc_tree_dump_ctx_t *dump_ctx; } 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_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_cprog(scc_ir_dump_ctx_t *ctx); +void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx); + #endif /* __SCC_IR_DUMP_H__ */ diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index 7062fab..13e0f8a 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -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, "\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)); + } +} diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 9cdb5a0..f264019 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -419,7 +419,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { token->type = type; goto END; default: - LEX_ERROR("unsupport char in sourse code `%c`", ch); + LEX_ERROR("unsupport char in sourse code `%c`:0x%x", ch, ch); break; } goto once_char; diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index bc9fe87..b07faa8 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -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)) { /// TODO // scc_parse_is_decl(); - scc_ast_node_type_t *ret = null; - ret = (scc_ast_node_type_t *)scc_parse_declaration(parser); + scc_ast_node_t *ret = null; + ret = (scc_ast_node_t *)scc_parse_declaration(parser); 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) { LOG_ERROR("Invalid statement");