diff --git a/libs/ast/include/ast_dump.h b/libs/ast/include/ast_dump.h index cdc5a2a..a72a56b 100644 --- a/libs/ast/include/ast_dump.h +++ b/libs/ast/include/ast_dump.h @@ -7,7 +7,7 @@ #define __SCC_AST_DUMP_H__ #include "ast_def.h" -#include +#include /** * @brief 以指定格式 dump AST @@ -15,6 +15,6 @@ * @param node AST 节点(可以是任意类型的节点) * @param ctx dump 上下文 */ -void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node); +void scc_ast_dump_node(scc_tree_dump_t *ctx, const scc_ast_node_t *node); #endif /* __SCC_AST_DUMP_H__ */ diff --git a/libs/ast/src/ast_dump.c b/libs/ast/src/ast_dump.c index 4c42c8d..01a82be 100644 --- a/libs/ast/src/ast_dump.c +++ b/libs/ast/src/ast_dump.c @@ -4,15 +4,7 @@ */ #include - -#define PRINT_VALUE(ctx, fmt, value) \ - SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->value_color, fmt, value) - -#define PRINT_NODE(ctx, name, value) \ - 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) +#include static const char *node_type_names[] = { [SCC_AST_UNKNOWN] = "Unknown", @@ -112,7 +104,6 @@ static const char *get_builtin_type_str(scc_ast_builtin_type_t type) { return builtin_type_names[type]; } -// 获取操作符字符串 static const char *get_op_str(scc_ast_expr_op_t op) { switch (op) { case SCC_AST_OP_ASSIGN: @@ -200,484 +191,374 @@ static const char *get_op_str(scc_ast_expr_op_t op) { } } -// 通用的开始节点打印函数 -static inline void start_node_dump(scc_ast_node_t *node, - scc_tree_dump_ctx_t *ctx) { - scc_tree_print_indent(ctx); - SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", - get_node_type_str(node->type)); -} - -// 通用的结束节点打印函数 -static inline void end_node_dump(scc_tree_dump_ctx_t *ctx) { - scc_tree_dump_printf(ctx, "\n"); -} - -// 通用的递归转储辅助函数 -static inline void dump_child_node(scc_ast_node_t *child, - scc_tree_dump_ctx_t *ctx, cbool is_last) { +static inline void dump_child_node(scc_tree_dump_t *td, scc_ast_node_t *child, + cbool is_last) { if (!child) return; - - scc_vec_push(ctx->stack, is_last); - scc_ast_dump_node(ctx, child); - (void)scc_vec_pop(ctx->stack); + scc_tree_dump_push(td, is_last); + scc_ast_dump_node(td, child); + scc_tree_dump_pop(td); } -// 用于构建复合类型名称的宏 -#define BUILD_TYPE_NAME(ctx, prefix, name) \ - do { \ - if (ctx->use_color) { \ - scc_tree_dump_printf(ctx, "%s'%s%s%s'%s", ctx->value_color, \ - prefix, name, ctx->reset_color, \ - ctx->reset_color); \ - } else { \ - scc_tree_dump_printf(ctx, "'%s%s'", prefix, name); \ - } \ - } while (0) - static inline void dump_quals(scc_ast_decl_specifier_t quals, - scc_tree_dump_ctx_t *ctx) { - if (quals.is_atomic) { - PRINT_QUOTED_VALUE(ctx, "atomic"); - } - if (quals.is_restrict) { - PRINT_QUOTED_VALUE(ctx, "restrict"); - } - if (quals.is_volatile) { - PRINT_QUOTED_VALUE(ctx, "volatile"); - } - if (quals.is_const) { - PRINT_QUOTED_VALUE(ctx, "const"); - } - if (quals.is_inline) { - PRINT_QUOTED_VALUE(ctx, "inline"); - } - if (quals.is_extern) { - PRINT_QUOTED_VALUE(ctx, "extern"); - } + scc_tree_dump_t *td) { + if (quals.is_atomic) + scc_tree_dump_value(td, " atomic"); + if (quals.is_restrict) + scc_tree_dump_value(td, " restrict"); + if (quals.is_volatile) + scc_tree_dump_value(td, " volatile"); + if (quals.is_const) + scc_tree_dump_value(td, " const"); + if (quals.is_inline) + scc_tree_dump_value(td, " inline"); + if (quals.is_extern) + scc_tree_dump_value(td, " extern"); } -// 递归转储类型 -static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) { +static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) { if (!type) return; - start_node_dump(&type->base, ctx); + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", get_node_type_str(type->base.type)); + dump_quals(type->quals, td); - dump_quals(type->quals, ctx); - - // 根据类型输出特定信息 switch (type->base.type) { case SCC_AST_TYPE_BUILTIN: - PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.type)); + scc_tree_dump_value(td, " '%s'", + get_builtin_type_str(type->builtin.type)); break; case SCC_AST_TYPE_POINTER: - PRINT_QUOTED_VALUE(ctx, "pointer"); + scc_tree_dump_value(td, " pointer"); break; case SCC_AST_TYPE_ARRAY: - PRINT_QUOTED_VALUE(ctx, "array"); + scc_tree_dump_value(td, " array"); break; case SCC_AST_TYPE_FUNCTION: - PRINT_QUOTED_VALUE(ctx, "function"); + scc_tree_dump_value(td, " function"); break; case SCC_AST_TYPE_STRUCT: - if (type->record.name) { - BUILD_TYPE_NAME(ctx, "struct ", type->record.name); - } else { - PRINT_QUOTED_VALUE(ctx, ""); - } + if (type->record.name) + scc_tree_dump_value(td, " 'struct %s'", type->record.name); + else + scc_tree_dump_value(td, " "); break; case SCC_AST_TYPE_UNION: - if (type->record.name) { - BUILD_TYPE_NAME(ctx, "union ", type->record.name); - } else { - PRINT_QUOTED_VALUE(ctx, ""); - } + if (type->record.name) + scc_tree_dump_value(td, " 'union %s'", type->record.name); + else + scc_tree_dump_value(td, " "); break; case SCC_AST_TYPE_ENUM: - if (type->record.name) { - BUILD_TYPE_NAME(ctx, "enum ", type->record.name); - } else { - PRINT_QUOTED_VALUE(ctx, "anonymous enum"); - } + if (type->record.name) + scc_tree_dump_value(td, " 'enum %s'", type->record.name); + else + scc_tree_dump_value(td, " anonymous enum"); break; case SCC_AST_TYPE_TYPEDEF: - PRINT_QUOTED_VALUE(ctx, type->typedef_type.name); + scc_tree_dump_value(td, " '%s'", type->typedef_type.name); break; default: break; } - end_node_dump(ctx); - - // 递归转储子节点 switch (type->base.type) { case SCC_AST_TYPE_POINTER: - dump_child_node((scc_ast_node_t *)type->pointer.pointee, ctx, true); + dump_child_node(td, (scc_ast_node_t *)type->pointer.pointee, true); break; case SCC_AST_TYPE_ARRAY: - dump_child_node((scc_ast_node_t *)type->array.element, ctx, + dump_child_node(td, (scc_ast_node_t *)type->array.element, type->array.size == NULL); - if (type->array.size) { - dump_child_node((scc_ast_node_t *)type->array.size, ctx, true); - } + if (type->array.size) + dump_child_node(td, (scc_ast_node_t *)type->array.size, true); break; case SCC_AST_TYPE_FUNCTION: - scc_vec_push(ctx->stack, false); - scc_tree_print_indent(ctx); - SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s\n", "ReturnType"); - dump_child_node((scc_ast_node_t *)type->function.return_type, ctx, - true); - (void)scc_vec_pop(ctx->stack); + scc_tree_dump_push(td, false); + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", "ReturnType"); + dump_child_node(td, (scc_ast_node_t *)type->function.return_type, true); + scc_tree_dump_pop(td); - scc_vec_push(ctx->stack, true); + scc_tree_dump_push(td, true); if (scc_vec_size(type->function.params) != 0) { scc_vec_foreach(type->function.params, i) { scc_ast_decl_t *param = scc_vec_at(type->function.params, i); - if (param->name) { - // FIXME param name - } - dump_type_impl(param->param.type, ctx); + dump_type_impl(param->param.type, td); } } else { - scc_tree_print_indent(ctx); - PRINT_QUOTED_VALUE(ctx, "()"); - scc_tree_dump_printf(ctx, "\n"); + scc_tree_dump_begin_line(td); + scc_tree_dump_value(td, "()"); } - (void)scc_vec_pop(ctx->stack); + scc_tree_dump_pop(td); break; default: break; } } -// 递归转储表达式 -static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) { +static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_t *td) { if (!expr) return; - start_node_dump(&expr->base, ctx); + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", get_node_type_str(expr->base.type)); - // 根据表达式类型输出特定信息 switch (expr->base.type) { case SCC_AST_EXPR_BINARY: - PRINT_QUOTED_VALUE(ctx, get_op_str(expr->binary.op)); + scc_tree_dump_value(td, " '%s'", get_op_str(expr->binary.op)); break; case SCC_AST_EXPR_UNARY: - PRINT_QUOTED_VALUE(ctx, get_op_str(expr->unary.op)); + scc_tree_dump_value(td, " '%s'", get_op_str(expr->unary.op)); break; case SCC_AST_EXPR_INT_LITERAL: case SCC_AST_EXPR_FLOAT_LITERAL: case SCC_AST_EXPR_CHAR_LITERAL: case SCC_AST_EXPR_STRING_LITERAL: - PRINT_VALUE(ctx, " %s", expr->literal.lexme); + scc_tree_dump_value(td, " %s", expr->literal.lexme); break; case SCC_AST_EXPR_IDENTIFIER: - if (expr->identifier.name) { - PRINT_QUOTED_VALUE(ctx, expr->identifier.name); - } + if (expr->identifier.name) + scc_tree_dump_value(td, " '%s'", expr->identifier.name); break; case SCC_AST_EXPR_SIZE_OF: case SCC_AST_EXPR_ALIGN_OF: - PRINT_QUOTED_VALUE(ctx, (expr->base.type == SCC_AST_EXPR_SIZE_OF) - ? "sizeof" - : "alignof"); + scc_tree_dump_value( + td, " '%s'", + (expr->base.type == SCC_AST_EXPR_SIZE_OF) ? "sizeof" : "alignof"); break; default: break; } - end_node_dump(ctx); - - // 使用辅助函数处理子节点转储 switch (expr->base.type) { case SCC_AST_EXPR_BINARY: - dump_child_node((scc_ast_node_t *)expr->binary.lhs, ctx, false); - dump_child_node((scc_ast_node_t *)expr->binary.rhs, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->binary.lhs, false); + dump_child_node(td, (scc_ast_node_t *)expr->binary.rhs, true); break; - case SCC_AST_EXPR_UNARY: - dump_child_node((scc_ast_node_t *)expr->unary.operand, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->unary.operand, true); break; - case SCC_AST_EXPR_COND: - dump_child_node((scc_ast_node_t *)expr->cond.cond, ctx, false); - dump_child_node((scc_ast_node_t *)expr->cond.then_expr, ctx, false); - dump_child_node((scc_ast_node_t *)expr->cond.else_expr, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->cond.cond, false); + dump_child_node(td, (scc_ast_node_t *)expr->cond.then_expr, false); + dump_child_node(td, (scc_ast_node_t *)expr->cond.else_expr, true); break; - case SCC_AST_EXPR_CALL: - dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false); - // 转储参数 + dump_child_node(td, (scc_ast_node_t *)expr->call.callee, false); for (size_t i = 0; i < expr->call.args.size; i++) { - dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx, + dump_child_node(td, (scc_ast_node_t *)expr->call.args.data[i], i == expr->call.args.size - 1); } break; - case SCC_AST_EXPR_ARRAY_SUBSCRIPT: - dump_child_node((scc_ast_node_t *)expr->subscript.array, ctx, false); - dump_child_node((scc_ast_node_t *)expr->subscript.index, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->subscript.array, false); + dump_child_node(td, (scc_ast_node_t *)expr->subscript.index, true); break; - case SCC_AST_EXPR_MEMBER: case SCC_AST_EXPR_PTR_MEMBER: - dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false); - scc_vec_push(ctx->stack, true); - scc_tree_print_indent(ctx); - SCC_TREE_DUMP_PRINT_PURE( - ctx, ctx->node_color, "%s %s\n", - expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember", - expr->member.name); - (void)scc_vec_pop(ctx->stack); + dump_child_node(td, (scc_ast_node_t *)expr->member.base, false); + scc_tree_dump_push(td, true); + scc_tree_dump_begin_line(td); + scc_tree_dump_node( + td, "%s", + expr->base.type == SCC_AST_EXPR_MEMBER ? "Member" : "PtrMember"); + scc_tree_dump_value(td, " %s", expr->member.name); + scc_tree_dump_pop(td); break; - case SCC_AST_EXPR_CAST: - dump_child_node((scc_ast_node_t *)expr->cast.type, ctx, false); - dump_child_node((scc_ast_node_t *)expr->cast.expr, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->cast.type, false); + dump_child_node(td, (scc_ast_node_t *)expr->cast.expr, true); break; - case SCC_AST_EXPR_SIZE_OF: case SCC_AST_EXPR_ALIGN_OF: - if (expr->attr_of.expr) { - dump_child_node((scc_ast_node_t *)expr->attr_of.expr, ctx, true); - } else if (expr->attr_of.type) { - dump_child_node((scc_ast_node_t *)expr->attr_of.type, ctx, true); - } + if (expr->attr_of.expr) + dump_child_node(td, (scc_ast_node_t *)expr->attr_of.expr, true); + else if (expr->attr_of.type) + dump_child_node(td, (scc_ast_node_t *)expr->attr_of.type, true); break; - case SCC_AST_EXPR_LVALUE: - dump_child_node((scc_ast_node_t *)expr->lvalue.type, ctx, true); + dump_child_node(td, (scc_ast_node_t *)expr->lvalue.type, true); break; - - case SCC_AST_EXPR_COMPOUND:; - dump_child_node((scc_ast_node_t *)expr->compound.base, ctx, false); - if (scc_vec_size(expr->compound.lhs_exprs) != - scc_vec_size(expr->compound.rhs_exprs)) { - LOG_ERROR("compound expr lhs and rhs size not equal"); - break; - } - usize size = scc_vec_size(expr->compound.lhs_exprs); - for (usize i = 0; i < size; i++) { - dump_child_node( - (scc_ast_node_t *)scc_vec_at(expr->compound.lhs_exprs, i), ctx, - false); - dump_child_node( - (scc_ast_node_t *)scc_vec_at(expr->compound.rhs_exprs, i), ctx, - i + 1 == size); + case SCC_AST_EXPR_COMPOUND: + dump_child_node(td, (scc_ast_node_t *)expr->compound.base, false); + { + usize size = scc_vec_size(expr->compound.lhs_exprs); + for (usize i = 0; i < size; i++) { + dump_child_node( + td, + (scc_ast_node_t *)scc_vec_at(expr->compound.lhs_exprs, i), + false); + dump_child_node( + td, + (scc_ast_node_t *)scc_vec_at(expr->compound.rhs_exprs, i), + i + 1 == size); + } } break; - - case SCC_AST_EXPR_BUILTIN: - // PRINT_QUOTED_VALUE(ctx, scc_ast_builtin_type_name(expr->builtin)); - break; - default: break; } } -// 递归转储语句 -static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) { +static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_t *td) { if (!stmt) return; - start_node_dump(&stmt->base, ctx); - // 根据语句类型输出特定信息 + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", get_node_type_str(stmt->base.type)); + switch (stmt->base.type) { - case SCC_AST_STMT_IF: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->if_stmt.cond, ctx, false); - dump_child_node((scc_ast_node_t *)stmt->if_stmt.then_stmt, ctx, - !stmt->if_stmt.opt_else_stmt); - if (stmt->if_stmt.opt_else_stmt) { - dump_child_node((scc_ast_node_t *)stmt->if_stmt.opt_else_stmt, ctx, - true); - } - return; - case SCC_AST_STMT_WHILE: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, false); - dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, true); - return; - case SCC_AST_STMT_DO_WHILE: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, false); - dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, true); - return; - case SCC_AST_STMT_SWITCH: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->switch_stmt.cond, ctx, false); - dump_child_node((scc_ast_node_t *)stmt->switch_stmt.body, ctx, true); - return; - case SCC_AST_STMT_FOR: - end_node_dump(ctx); - if (stmt->for_stmt.init) { - dump_child_node((scc_ast_node_t *)stmt->for_stmt.init, ctx, false); - } - if (stmt->for_stmt.cond) { - dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false); - } - if (stmt->for_stmt.incr) { - dump_child_node((scc_ast_node_t *)stmt->for_stmt.incr, ctx, false); - } - dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true); - return; case SCC_AST_STMT_RETURN: - if (stmt->return_stmt.expr) { - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->return_stmt.expr, ctx, - true); - } else { - end_node_dump(ctx); + if (!stmt->return_stmt.expr) { + return; } - break; + dump_child_node(td, (scc_ast_node_t *)stmt->return_stmt.expr, true); + return; case SCC_AST_STMT_GOTO: - if (stmt->goto_stmt.label) { - PRINT_VALUE(ctx, " Label: %s", stmt->goto_stmt.label); - } - end_node_dump(ctx); - break; + if (stmt->goto_stmt.label) + scc_tree_dump_value(td, " Label: %s", stmt->goto_stmt.label); + return; case SCC_AST_STMT_LABEL: - if (stmt->label_stmt.label) { - PRINT_VALUE(ctx, " %s", stmt->label_stmt.label); - } - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->label_stmt.stmt, ctx, true); - break; - case SCC_AST_STMT_COMPOUND: - end_node_dump(ctx); - scc_vec_foreach(stmt->compound.block_items, i) { - dump_child_node( - (scc_ast_node_t *)scc_vec_at(stmt->compound.block_items, i), - ctx, i + 1 == stmt->compound.block_items.size); - } - break; - - case SCC_AST_STMT_EXPR: - end_node_dump(ctx); - if (stmt->expr.expr) { - dump_child_node((scc_ast_node_t *)stmt->expr.expr, ctx, true); - } - break; - - case SCC_AST_STMT_CASE: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->case_stmt.expr, ctx, false); - dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true); - break; - + if (stmt->label_stmt.label) + scc_tree_dump_value(td, " %s", stmt->label_stmt.label); + dump_child_node(td, (scc_ast_node_t *)stmt->label_stmt.stmt, true); + return; case SCC_AST_STMT_BREAK: case SCC_AST_STMT_CONTINUE: - end_node_dump(ctx); - break; - + return; case SCC_AST_STMT_DEFAULT: - end_node_dump(ctx); - dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true); - break; - + dump_child_node(td, (scc_ast_node_t *)stmt->default_stmt.stmt, true); + return; + case SCC_AST_STMT_COMPOUND: + scc_vec_foreach(stmt->compound.block_items, i) { + dump_child_node( + td, (scc_ast_node_t *)scc_vec_at(stmt->compound.block_items, i), + i + 1 == stmt->compound.block_items.size); + } + return; + case SCC_AST_STMT_EXPR: + if (stmt->expr.expr) + dump_child_node(td, (scc_ast_node_t *)stmt->expr.expr, true); + return; + case SCC_AST_STMT_IF: + dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.cond, false); + dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.then_stmt, + !stmt->if_stmt.opt_else_stmt); + if (stmt->if_stmt.opt_else_stmt) + dump_child_node(td, (scc_ast_node_t *)stmt->if_stmt.opt_else_stmt, + true); + return; + case SCC_AST_STMT_WHILE: + dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.cond, false); + dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.body, true); + return; + case SCC_AST_STMT_DO_WHILE: + dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.body, false); + dump_child_node(td, (scc_ast_node_t *)stmt->while_stmt.cond, true); + return; + case SCC_AST_STMT_SWITCH: + dump_child_node(td, (scc_ast_node_t *)stmt->switch_stmt.cond, false); + dump_child_node(td, (scc_ast_node_t *)stmt->switch_stmt.body, true); + return; + case SCC_AST_STMT_FOR: + if (stmt->for_stmt.init) + dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.init, false); + if (stmt->for_stmt.cond) + dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.cond, false); + if (stmt->for_stmt.incr) + dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.incr, false); + dump_child_node(td, (scc_ast_node_t *)stmt->for_stmt.body, true); + return; + case SCC_AST_STMT_CASE: + dump_child_node(td, (scc_ast_node_t *)stmt->case_stmt.expr, false); + dump_child_node(td, (scc_ast_node_t *)stmt->case_stmt.stmt, true); + return; default: - LOG_WARN("unknown node type %d", stmt->base.type); break; } } -// 递归转储声明 -static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) { +static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) { if (!decl) return; - start_node_dump(&decl->base, ctx); - if (decl->name) { - PRINT_QUOTED_VALUE(ctx, decl->name); - } - end_node_dump(ctx); + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", get_node_type_str(decl->base.type)); + if (decl->name) + scc_tree_dump_value(td, " '%s'", decl->name); - // 递归转储子节点 switch (decl->base.type) { case SCC_AST_DECL_LIST: scc_vec_foreach(decl->list.vars, i) { - dump_child_node((scc_ast_node_t *)scc_vec_at(decl->list.vars, i), - ctx, i + 1 == scc_vec_size(decl->list.vars)); + dump_child_node(td, + (scc_ast_node_t *)scc_vec_at(decl->list.vars, i), + i + 1 == scc_vec_size(decl->list.vars)); } break; case SCC_AST_DECL_VAR: if (decl->var.type) { - dump_child_node((scc_ast_node_t *)decl->var.type, ctx, + dump_child_node(td, (scc_ast_node_t *)decl->var.type, decl->var.init == NULL); - if (decl->var.init) { - dump_child_node((scc_ast_node_t *)decl->var.init, ctx, true); - } + if (decl->var.init) + dump_child_node(td, (scc_ast_node_t *)decl->var.init, true); } break; - case SCC_AST_DECL_FUNC: if (decl->func.type) { - dump_child_node((scc_ast_node_t *)decl->func.type, ctx, - decl->func.body == null); - if (decl->func.body) { - dump_child_node((scc_ast_node_t *)decl->func.body, ctx, true); - } + dump_child_node(td, (scc_ast_node_t *)decl->func.type, + decl->func.body == NULL); + if (decl->func.body) + dump_child_node(td, (scc_ast_node_t *)decl->func.body, true); } break; - case SCC_AST_DECL_PARAM: - if (decl->param.type) { - dump_child_node((scc_ast_node_t *)decl->param.type, ctx, true); - } + if (decl->param.type) + dump_child_node(td, (scc_ast_node_t *)decl->param.type, true); break; - case SCC_AST_DECL_STRUCT: case SCC_AST_DECL_UNION: case SCC_AST_DECL_ENUM: scc_vec_foreach(decl->record.fields, i) { dump_child_node( - (scc_ast_node_t *)scc_vec_at(decl->record.fields, i), ctx, + td, (scc_ast_node_t *)scc_vec_at(decl->record.fields, i), i + 1 == scc_vec_size(decl->record.fields)); } break; - case SCC_AST_DECL_TYPEDEF: - if (decl->typedef_decl.type) { - dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx, + if (decl->typedef_decl.type) + dump_child_node(td, (scc_ast_node_t *)decl->typedef_decl.type, true); - } break; - default: break; } } -// 递归转储翻译单元 static void dump_unit_impl(scc_ast_translation_unit_t *unit, - scc_tree_dump_ctx_t *ctx) { + scc_tree_dump_t *td) { if (!unit) return; - start_node_dump(&unit->base, ctx); - end_node_dump(ctx); + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "%s", get_node_type_str(unit->base.type)); scc_vec_foreach(unit->declarations, i) { - dump_child_node((scc_ast_node_t *)scc_vec_at(unit->declarations, i), - ctx, i + 1 == scc_vec_size(unit->declarations)); + dump_child_node(td, (scc_ast_node_t *)scc_vec_at(unit->declarations, i), + i + 1 == scc_vec_size(unit->declarations)); } } -void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node) { +void scc_ast_dump_node(scc_tree_dump_t *td, const scc_ast_node_t *node) { if (!node) return; - - if (SCC_AST_IS_A(scc_ast_expr_t, node)) { - dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), ctx); - } else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) { - dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), ctx); - } else if (SCC_AST_IS_A(scc_ast_decl_t, node)) { - dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), ctx); - } else if (SCC_AST_IS_A(scc_ast_type_t, node)) { - dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), ctx); - } else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) { - dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), ctx); - } + if (SCC_AST_IS_A(scc_ast_expr_t, node)) + dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), td); + else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) + dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), td); + else if (SCC_AST_IS_A(scc_ast_decl_t, node)) + dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), td); + else if (SCC_AST_IS_A(scc_ast_type_t, node)) + dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), td); + else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) + dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), td); } diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index d8cc348..d1971be 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -93,6 +93,92 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, return scc_ir_builder_type(&ctx->builder, &ir_type); } +scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx, + scc_ast_expr_t *expr, + scc_ir_value_ref_t lhs, + scc_ir_value_ref_t rhs) { + scc_ir_bblock_ref_t start_block = + scc_ir_builder_current_bblock(&ctx->builder); + + scc_ir_bblock_ref_t right_block = + scc_ir_builder_bblock(&ctx->builder, "logic_right"); + scc_ir_bblock_ref_t end_block = + scc_ir_builder_bblock(&ctx->builder, "logic_end"); + + // 为结果创建临时存储空间 + scc_ir_type_ref_t int32_type = scc_ir_builder_type_i32(&ctx->builder); + scc_ir_value_ref_t result_var = + scc_ir_builder_alloca(&ctx->builder, int32_type, "logic_result"); + + // 计算左操作数 + scc_ir_value_ref_t left_val = scc_ast2ir_expr(ctx, expr->binary.lhs, false); + scc_ir_value_ref_t zero_val = scc_ir_builder_const_int( + &ctx->builder, int32_type, (scc_ir_const_int_t){.int32 = 0}); + scc_ir_value_ref_t one_val = scc_ir_builder_const_int( + &ctx->builder, int32_type, (scc_ir_const_int_t){.int32 = 1}); + + if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) { + // a && b + scc_ir_bblock_ref_t false_block = + scc_ir_builder_bblock(&ctx->builder, "and_false"); + + // 如果左操作数为0,结果为0(短路) + scc_ir_value_ref_t is_left_zero = scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_EQ, left_val, zero_val); + scc_ir_builder_branch(&ctx->builder, is_left_zero, false_block, + right_block); + + // false_block: 左边为0,结果为0 + scc_ir_builder_set_current_bblock(&ctx->builder, false_block); + scc_ir_builder_store(&ctx->builder, result_var, zero_val); + scc_ir_builder_jump(&ctx->builder, end_block); + + // right_block: 左边非0,计算右边 + scc_ir_builder_set_current_bblock(&ctx->builder, right_block); + scc_ir_value_ref_t right_val = + scc_ast2ir_expr(ctx, expr->binary.rhs, false); + scc_ir_value_ref_t is_right_zero = scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_EQ, right_val, zero_val); + scc_ir_value_ref_t result = + scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_XOR, is_right_zero, + one_val); // !right == 0 ? 1 : 0 + scc_ir_builder_store(&ctx->builder, result_var, result); + scc_ir_builder_jump(&ctx->builder, end_block); + + } else { // SCC_AST_OP_LOGICAL_OR + // a || b + scc_ir_bblock_ref_t true_block = + scc_ir_builder_bblock(&ctx->builder, "or_true"); + + // 如果左操作数非0,结果为1(短路) + scc_ir_value_ref_t is_left_nonzero = scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_NEQ, left_val, zero_val); + scc_ir_builder_branch(&ctx->builder, is_left_nonzero, true_block, + right_block); + + // true_block: 左边非0,结果为1 + scc_ir_builder_set_current_bblock(&ctx->builder, true_block); + scc_ir_builder_store(&ctx->builder, result_var, one_val); + scc_ir_builder_jump(&ctx->builder, end_block); + + // right_block: 左边为0,计算右边 + scc_ir_builder_set_current_bblock(&ctx->builder, right_block); + scc_ir_value_ref_t right_val = + scc_ast2ir_expr(ctx, expr->binary.rhs, false); + scc_ir_value_ref_t is_right_zero = scc_ir_builder_binop( + &ctx->builder, SCC_IR_OP_EQ, right_val, zero_val); + scc_ir_value_ref_t result = + scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_XOR, is_right_zero, + one_val); // !right == 0 ? 1 : 0 + scc_ir_builder_store(&ctx->builder, result_var, result); + scc_ir_builder_jump(&ctx->builder, end_block); + } + + // 设置结束块为当前块,并返回结果 + scc_ir_builder_set_current_bblock(&ctx->builder, end_block); + return scc_ir_builder_load(&ctx->builder, result_var); +} + /** * @brief * @@ -218,7 +304,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, /* 逻辑操作符 */ case SCC_AST_OP_LOGICAL_OR: // || case SCC_AST_OP_LOGICAL_AND: // && - TODO(); + return scc_ast2ir_logical_expr(ctx, expr, lhs, rhs); /* clang-format on */ default: LOG_FATAL("Unsupported binary operator: %d", expr->binary.op); @@ -243,6 +329,9 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, // SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀) // SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀) switch (expr->unary.op) { + case SCC_AST_OP_UNARY_PLUS: + /* just pass */ + return operand; case SCC_AST_OP_UNARY_MINUS: { // 负号 // 实现为0 - operand @@ -254,6 +343,28 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_SUB, zero_ref, operand); } + case SCC_AST_OP_ADDRESS_OF: + // 取地址 + operand = + scc_ir_builder_get_ptr(&ctx->builder, operand, SCC_IR_REF_NULL); + Assert(operand != SCC_IR_REF_NULL); + return operand; + case SCC_AST_OP_INDIRECTION: + // 从地址取值 + // FIXME + scc_ir_value_t *value = + scc_ir_module_get_value(ctx->builder.ctx.module, operand); + Assert(value != null); + scc_ir_type_t *type = + scc_ir_module_get_type(ctx->builder.ctx.module, value->type); + Assert(type != null); + if (type->tag != SCC_IR_TYPE_PTR) { + LOG_FATAL("Invalid type: %d", type->tag); + } + + operand = scc_ir_builder_load(&ctx->builder, operand); + Assert(operand != SCC_IR_REF_NULL); + return operand; case SCC_AST_OP_BITWISE_NOT: // 按位取反 return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_NOT, operand, @@ -327,9 +438,37 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, return scc_ir_builder_const_int(&ctx->builder, type_ref, value); } - // SCC_AST_EXPR_INT_LITERAL, // 整数字面量 // SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量 - // SCC_AST_EXPR_CHAR_LITERAL, // 字符字面量 + case SCC_AST_EXPR_CHAR_LITERAL: { + // FIXME just 'a' '\n' + scc_ir_type_ref_t type_ref = scc_ir_builder_type_i32(&ctx->builder); + const char *lexme = expr->literal.lexme; + Assert(lexme[0] == '\''); + u8 int_lit = 0; + if (lexme[1] == '\\') { + switch (lexme[2]) { + case 'a': + int_lit = '\a'; + break; + case 'b': + int_lit = '\b'; + break; + case 'f': + int_lit = '\f'; + break; + case 'n': + int_lit = '\n'; + break; + case 'r': + int_lit = '\r'; + } + } else { + int_lit = lexme[1]; + } + scc_ir_const_int_t value; + value.int32 = int_lit; + return scc_ir_builder_const_int(&ctx->builder, type_ref, value); + } case SCC_AST_EXPR_STRING_LITERAL: { // FIXME scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme, diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index 3baf11f..31b635c 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -86,7 +86,7 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str, scc_ir_type_t array_type = { .tag = SCC_IR_TYPE_ARRAY, .data.array.base = u8_type, - .data.array.len = len + 1, // 包含 null 结尾 + .data.array.len = len - 1, // 包含 null 结尾 }; scc_ir_type_ref_t array_type_ref = scc_ir_ctx_get_type(&builder->ctx, &array_type); @@ -103,14 +103,15 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str, .type = array_type_ref, .data.const_array.base_type = u8_type, }; - char *buff = scc_malloc(len + 1); + char *buff = scc_malloc(len - 1); Assert(buff); - for (usize i = 0; i < len; i++) { - buff[i] = str[i]; + // FIXME content to real string + for (usize i = 1; i < len - 1; i++) { + buff[i - 1] = str[i]; } - buff[len] = '\0'; + buff[len - 2] = '\0'; scc_vec_unsafe_from_buffer(const_array_value.data.const_array.elements, - buff, len + 1); + buff, len - 1); scc_ir_value_ref_t const_array_ref = scc_ir_module_add_value(builder->ctx.module, &const_array_value); Assert(const_array_ref != SCC_IR_REF_NULL); @@ -182,6 +183,7 @@ scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder, */ void scc_ir_builder_end_bblock(scc_ir_builder_t *builder); +scc_ir_func_ref_t scc_ir_builder_current_bblock(scc_ir_builder_t *builder); /** * @brief 设置当前基本块 */ diff --git a/libs/ir/include/ir_dump.h b/libs/ir/include/ir_dump.h index aae015c..44ee370 100644 --- a/libs/ir/include/ir_dump.h +++ b/libs/ir/include/ir_dump.h @@ -2,15 +2,14 @@ #define __SCC_IR_DUMP_H__ #include "ir_prog.h" -#include +#include typedef struct { scc_ir_cprog_t *cprog; - scc_tree_dump_ctx_t *dump_ctx; + scc_tree_dump_t *dump_ctx; } scc_ir_dump_ctx_t; -void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx, - scc_tree_dump_ctx_t *tree_dump, +void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx, scc_tree_dump_t *tree_dump, scc_ir_cprog_t *cprog); void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref); void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref); diff --git a/libs/ir/include/ir_module.h b/libs/ir/include/ir_module.h index 390ecd3..ed96e57 100644 --- a/libs/ir/include/ir_module.h +++ b/libs/ir/include/ir_module.h @@ -39,4 +39,11 @@ scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx, scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx, scc_ir_func_ref_t ref); +static inline scc_ir_type_t * +scc_ir_module_get_type_by_value(scc_ir_module_t *ctx, scc_ir_value_ref_t ref) { + scc_ir_value_t *value = scc_ir_module_get_value(ctx, ref); + Assert(value != null); + return scc_ir_module_get_type(ctx, value->type); +} + #endif /* __SCC_IR_MODULE_H__ */ diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index e7e1507..0b74697 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -129,6 +129,10 @@ void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder, builder->current_bblock = bblock; } +scc_ir_func_ref_t scc_ir_builder_current_bblock(scc_ir_builder_t *builder) { + return builder->current_bblock; +} + void scc_ir_builder_add_instr(scc_ir_builder_t *builder, scc_ir_value_ref_t instr) { scc_ir_bblock_t *current_bblock = @@ -205,6 +209,7 @@ scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder, scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder, scc_ir_value_ref_t target, scc_ir_value_ref_t value) { + Assert(target != SCC_IR_REF_NULL && value != SCC_IR_REF_NULL); scc_ir_value_t store_node = {0}; store_node.tag = SCC_IR_VALUE_TAG_STORE; store_node.data.store.target = target; diff --git a/libs/ir/src/ir_ctx.c b/libs/ir/src/ir_ctx.c index ba7c2ee..eb08d8d 100644 --- a/libs/ir/src/ir_ctx.c +++ b/libs/ir/src/ir_ctx.c @@ -112,7 +112,7 @@ static int cmp_type(const void *_key1, const void *_key2) { return 0; } default: - UNREACHABLE(); + Panic("Unknown key type %d", key1->tag); return 1; } return 1; diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index eddff51..2313bdc 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -1,18 +1,9 @@ #include #include +#include #define GET_MODULE(ctx) (&(ctx->cprog->module)) -#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_value_tag_t tag) { static const char *node_types[] = { [SCC_IR_VALUE_TAG_NULL] = "Null", @@ -21,31 +12,27 @@ static const char *get_node_type_str(scc_ir_value_tag_t tag) { [SCC_IR_VALUE_TAG_CONST_FLOAT] = "ConstFloat", [SCC_IR_VALUE_TAG_CONST_ARRAY] = "ConstArray", [SCC_IR_VALUE_TAG_AGGREGATE] = "Aggregate", - [SCC_IR_VALUE_TAG_CONV] = "Convert", ///< 类型转换 - [SCC_IR_VALUE_TAG_FUNC_ARG_REF] = "FuncArgRef", ///< 函数参数引用 - [SCC_IR_VALUE_TAG_BLOCK_ARG_REF] = "BlockArgRef", ///< 基本块参数引用 - [SCC_IR_VALUE_TAG_ALLOC] = "Alloc", ///< 分配内存(stack) - [SCC_IR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc", ///< 全局分配(bss) - [SCC_IR_VALUE_TAG_LOAD] = "Load", ///< 加载数据 - [SCC_IR_VALUE_TAG_STORE] = "Store", ///< 存储数据 - [SCC_IR_VALUE_TAG_GET_PTR] = "GetPtr", ///< 获取指针 - [SCC_IR_VALUE_TAG_GET_ELEM_PTR] = - "GetElemPtr", ///< 获取元素指针(used by array) - [SCC_IR_VALUE_TAG_OP] = "Op", ///< 二元运算 - [SCC_IR_VALUE_TAG_BRANCH] = "Branch", ///< 有条件分支 - [SCC_IR_VALUE_TAG_JUMP] = "Jump", ///< 无条件跳转 - [SCC_IR_VALUE_TAG_CALL] = "Call", ///< 调用函数 - [SCC_IR_VALUE_TAG_RET] = "Ret", ///< 函数返回 + [SCC_IR_VALUE_TAG_CONV] = "Convert", + [SCC_IR_VALUE_TAG_FUNC_ARG_REF] = "FuncArgRef", + [SCC_IR_VALUE_TAG_BLOCK_ARG_REF] = "BlockArgRef", + [SCC_IR_VALUE_TAG_ALLOC] = "Alloc", + [SCC_IR_VALUE_TAG_GLOBAL_ALLOC] = "GlobalAlloc", + [SCC_IR_VALUE_TAG_LOAD] = "Load", + [SCC_IR_VALUE_TAG_STORE] = "Store", + [SCC_IR_VALUE_TAG_GET_PTR] = "GetPtr", + [SCC_IR_VALUE_TAG_GET_ELEM_PTR] = "GetElemPtr", + [SCC_IR_VALUE_TAG_OP] = "Op", + [SCC_IR_VALUE_TAG_BRANCH] = "Branch", + [SCC_IR_VALUE_TAG_JUMP] = "Jump", + [SCC_IR_VALUE_TAG_CALL] = "Call", + [SCC_IR_VALUE_TAG_RET] = "Ret", }; - if (tag >= 0 && (usize)tag < sizeof(node_types) / sizeof(node_types[0]) && - node_types[tag] != NULL) { + node_types[tag]) return node_types[tag]; - } return "UnknownIRNode"; } -// 获取操作符字符串 static const char *get_op_str(scc_ir_op_type_t op) { static const char *ops[] = { [SCC_IR_OP_EMPTY] = "empty", [SCC_IR_OP_NEQ] = "!=", @@ -57,17 +44,13 @@ static const char *get_op_str(scc_ir_op_type_t op) { [SCC_IR_OP_AND] = "&", [SCC_IR_OP_OR] = "|", [SCC_IR_OP_XOR] = "^", [SCC_IR_OP_NOT] = "~", [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>", - [SCC_IR_OP_SAR] = ">>a", // Arithmetic shift right + [SCC_IR_OP_SAR] = ">>a", }; - - if (op >= 0 && (usize)op < sizeof(ops) / sizeof(ops[0]) && - ops[op] != NULL) { + if (op >= 0 && (usize)op < sizeof(ops) / sizeof(ops[0]) && ops[op]) 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_u8] = "u8", @@ -81,194 +64,139 @@ static const char *get_type_tag_str(scc_ir_type_tag_t tag) { [SCC_IR_TYPE_ARRAY] = "array", [SCC_IR_TYPE_FUNC] = "func", [SCC_IR_TYPE_STRUCT] = "struct", [SCC_IR_TYPE_VECTOR] = "vector", }; - if (tag >= 0 && (usize)tag < sizeof(type_tags) / sizeof(type_tags[0]) && - type_tags[tag] != NULL) { + type_tags[tag]) return type_tags[tag]; - } return ""; } -// 递归转储辅助函数(使用引用) static inline void dump_child_node_ref(scc_ir_dump_ctx_t *ctx, - scc_ir_value_ref_t child_ref, + scc_ir_value_ref_t child, cbool is_last) { - if (!child_ref) + if (!child) return; - scc_tree_dump_push_level(ctx->dump_ctx, is_last); - scc_ir_dump_value(ctx, child_ref); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_dump_value(ctx, child); + scc_tree_dump_pop(ctx->dump_ctx); } -// 转储常量整数节点 static void dump_const_int_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) { - scc_tree_dump_push_level(ctx->dump_ctx, true); - scc_tree_print_indent(ctx->dump_ctx); - scc_tree_dump_printf(ctx->dump_ctx, "%d\n", node->data.const_int.int32); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_push(ctx->dump_ctx, true); + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_value(ctx->dump_ctx, "%d", node->data.const_int.int32); + scc_tree_dump_pop(ctx->dump_ctx); } -// 转储操作节点 static void dump_op_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_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); + 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(node->data.op.op)); + scc_tree_dump_pop(ctx->dump_ctx); - // 左操作数 - if (node->data.op.lhs) { + 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) { + 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_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "load"); - if (node->data.load.target) { + 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_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "store"); - - // 输出存储位置 - if (node->data.store.target) { + if (node->data.store.target) dump_child_node_ref(ctx, node->data.store.target, false); - } - - // 输出存储的值 - if (node->data.store.value) { + 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_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "get_ptr"); - // 输出源地址 - if (node->data.get_ptr.src_addr) { + 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) { + 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_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "branch"); - - // 输出条件 - if (node->data.branch.cond) { + 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_module_get_bblock( GET_MODULE(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 - : ""); + 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->label ? true_bblock->label + : ""); } } - - // 输出假分支块 if (node->data.branch.false_bblock) { scc_ir_bblock_t *false_bblock = scc_ir_module_get_bblock( GET_MODULE(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 - : ""); + 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->label ? false_bblock->label + : ""); } } } -// 转储跳转节点 static void dump_jump_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "jump"); + scc_tree_dump_begin_line(ctx->dump_ctx); if (node->data.jump.target_bblock) { - scc_ir_bblock_t *target_bblock = scc_ir_module_get_bblock( + scc_ir_bblock_t *target = scc_ir_module_get_bblock( GET_MODULE(ctx), node->data.jump.target_bblock); - if (target_bblock) { - scc_tree_dump_printf(ctx->dump_ctx, "to '%s'", - target_bblock->label ? target_bblock->label - : ""); - } else { - scc_tree_dump_printf(ctx->dump_ctx, "to invalid block"); - } + if (target) + scc_tree_dump_value(ctx->dump_ctx, "to '%s'", + target->label ? target->label : ""); + else + scc_tree_dump_value(ctx->dump_ctx, "to invalid block"); } else { - scc_tree_dump_printf(ctx->dump_ctx, "to NULL"); + scc_tree_dump_value(ctx->dump_ctx, "to NULL"); } } -// 转储调用节点 static void dump_call_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "call"); + scc_tree_dump_begin_line(ctx->dump_ctx); if (node->data.call.callee) { scc_ir_func_t *callee = scc_ir_module_get_func(GET_MODULE(ctx), node->data.call.callee); - if (callee) { - scc_tree_dump_printf(ctx->dump_ctx, "func='%s'", - callee->name ? callee->name : ""); - } else { - scc_tree_dump_printf(ctx->dump_ctx, "func="); - } + scc_tree_dump_value(ctx->dump_ctx, "func='%s'", + callee ? (callee->name ? callee->name : "") + : ""); } else { - scc_tree_dump_printf(ctx->dump_ctx, "func=NULL"); + scc_tree_dump_value(ctx->dump_ctx, "func=NULL"); } - if (scc_vec_size(node->data.call.args) > 0) { - scc_tree_dump_printf(ctx->dump_ctx, "\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_value_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); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_value_ref_t arg = scc_vec_at(node->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_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) { - // PRINT_NODE(ctx->dump_ctx, "ret"); - if (node->data.ret.ret_val) { + 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, +void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx, scc_tree_dump_t *td, scc_ir_cprog_t *cprog) { ctx->cprog = cprog; - ctx->dump_ctx = tree_dump; + ctx->dump_ctx = td; } void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref) { @@ -278,28 +206,21 @@ void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t 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); - } - + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_node(ctx->dump_ctx, "%s", get_node_type_str(node->tag)); + if (node->name && node->name[0]) + scc_tree_dump_value(ctx->dump_ctx, " [%s]", node->name); if (node->type) { - scc_tree_dump_printf(ctx->dump_ctx, " : "); scc_ir_type_t *type = scc_ir_module_get_type(GET_MODULE(ctx), node->type); if (type) { - PRINT_VALUE(ctx->dump_ctx, "%s", get_type_tag_str(type->tag)); + scc_tree_dump_append(ctx->dump_ctx, " : "); + scc_tree_dump_value(ctx->dump_ctx, "%s", + get_type_tag_str(type->tag)); } } - scc_tree_dump_printf(ctx->dump_ctx, "\n"); - - // 根据节点类型输出特定信息 switch (node->tag) { - case SCC_IR_VALUE_TAG_NULL: - break; case SCC_IR_VALUE_TAG_CONST_INT: dump_const_int_node(ctx, node); break; @@ -330,206 +251,133 @@ void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref) { dump_ret_node(ctx, node); break; default: - PRINT_QUOTED_VALUE(ctx->dump_ctx, "unknown"); - scc_tree_dump_printf(ctx->dump_ctx, "tag(%d)", node->tag); + scc_tree_dump_value(ctx->dump_ctx, "unknown"); + scc_tree_dump_append_fmt(ctx->dump_ctx, " 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_module_get_type(GET_MODULE(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_tree_dump_printf(ctx->dump_ctx, "\n"); + 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_IR_TYPE_PTR: if (type->data.pointer.base) { - scc_tree_dump_push_level(ctx->dump_ctx, true); + scc_tree_dump_push(ctx->dump_ctx, true); scc_ir_dump_type(ctx, type->data.pointer.base); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_pop(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); + 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_level(ctx->dump_ctx, true); + scc_tree_dump_push(ctx->dump_ctx, true); scc_ir_dump_type(ctx, type->data.array.base); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_pop(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); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_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_level(ctx->dump_ctx, true); + scc_tree_dump_push(ctx->dump_ctx, true); scc_ir_dump_type(ctx, type->data.function.ret_type); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_pop(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_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->label ? bblock->label : ""); + scc_tree_dump_append(ctx->dump_ctx, "\n"); - scc_tree_print_indent(ctx->dump_ctx); - PRINT_NODE(ctx->dump_ctx, "BasicBlock: "); - PRINT_QUOTED_VALUE(ctx->dump_ctx, - bblock->label ? bblock->label : ""); - scc_tree_dump_printf(ctx->dump_ctx, "\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_value_ref_t instr_ref = scc_vec_at(bblock->instrs, i); - scc_ir_dump_value(ctx, instr_ref); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_dump_value(ctx, scc_vec_at(bblock->instrs, i)); + scc_tree_dump_pop(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_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 : ""); + scc_tree_dump_append(ctx->dump_ctx, "\n"); - scc_tree_print_indent(ctx->dump_ctx); - PRINT_NODE(ctx->dump_ctx, "Function: "); - PRINT_QUOTED_VALUE(ctx->dump_ctx, func->name ? func->name : ""); - scc_tree_dump_printf(ctx->dump_ctx, "\n"); - - // 输出函数类型 if (func->type) { - scc_tree_dump_push_level(ctx->dump_ctx, false); + scc_tree_dump_push(ctx->dump_ctx, false); scc_ir_dump_type(ctx, func->type); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_pop(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_value_ref_t param_ref = scc_vec_at(func->params, i); - scc_ir_dump_value(ctx, param_ref); - scc_tree_dump_pop_level(ctx->dump_ctx); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_dump_value(ctx, scc_vec_at(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_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); + scc_tree_dump_push(ctx->dump_ctx, is_last); + scc_ir_dump_bblock(ctx, scc_vec_at(func->bblocks, i)); + scc_tree_dump_pop(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_value_ref_t global_ref = - // scc_vec_at(program->global_vals, i); scc_ir_value_t - // *global_node = - // scc_ir_module_get_value(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_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_level(ctx->dump_ctx, is_last); + scc_tree_dump_push(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); + scc_tree_dump_pop(ctx->dump_ctx); } } +// ----- 线性输出(保留原逻辑,改用新 API)----- 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_module_get_type(GET_MODULE(ctx), type_ref); @@ -537,7 +385,6 @@ void scc_ir_dump_type_linear(scc_ir_dump_ctx_t *ctx, LOG_ERROR("invalid parameter"); return; } -#define PRINT_TYPE(ctx, name) PRINT_VALUE(ctx, "%s", name) switch (type->tag) { case SCC_IR_TYPE_unknown: case SCC_IR_TYPE_void: @@ -555,35 +402,30 @@ void scc_ir_dump_type_linear(scc_ir_dump_ctx_t *ctx, case SCC_IR_TYPE_f32: case SCC_IR_TYPE_f64: case SCC_IR_TYPE_f128: - PRINT_TYPE(ctx->dump_ctx, get_type_tag_str(type->tag)); + scc_tree_dump_value(ctx->dump_ctx, "%s", get_type_tag_str(type->tag)); break; case SCC_IR_TYPE_ARRAY: - PRINT_TYPE(ctx->dump_ctx, "["); + scc_tree_dump_append(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, "]"); + scc_tree_dump_append_fmt(ctx->dump_ctx, ", %zu]", type->data.array.len); break; case SCC_IR_TYPE_PTR: - PRINT_TYPE(ctx->dump_ctx, "*"); + scc_tree_dump_append(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_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_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_tree_dump_append(ctx->dump_ctx, ") -> "); scc_ir_dump_type_linear(ctx, type->data.function.ret_type); } else { - PRINT_TYPE(ctx->dump_ctx, ")"); + scc_tree_dump_append(ctx->dump_ctx, ")"); } break; default: @@ -592,347 +434,247 @@ void scc_ir_dump_type_linear(scc_ir_dump_ctx_t *ctx, } } -// 辅助函数:输出节点引用或值到缓冲区 -static usize format_node_ref_or_value(scc_ir_dump_ctx_t *ctx, char *buf, - usize size, scc_ir_value_ref_t node_ref) { +static void format_node_ref_or_value(scc_ir_dump_ctx_t *ctx, + scc_ir_value_ref_t node_ref) { scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref); if (!node) { - return scc_snprintf(buf, size, "%%%u", node_ref); + scc_tree_dump_append_fmt(ctx->dump_ctx, "%%%u", node_ref); + return; } - - // 如果是常量整数,直接输出值 if (node->tag == SCC_IR_VALUE_TAG_CONST_INT) { - return scc_snprintf(buf, size, "%d", node->data.const_int.int32); + scc_tree_dump_append_fmt(ctx->dump_ctx, "%d", + node->data.const_int.int32); + return; } - - // 其他节点输出引用和名称 if (node->name && node->name[0] != '\0') { - return scc_snprintf(buf, size, "%%%u[%s]", node_ref, node->name); + scc_tree_dump_node(ctx->dump_ctx, "%%%u[%s]", node_ref, node->name); } else { - return scc_snprintf(buf, size, "%%%u", node_ref); + scc_tree_dump_node(ctx->dump_ctx, "%%%u", node_ref); + } + if (node->type != SCC_IR_REF_NULL) { + scc_tree_dump_append(ctx->dump_ctx, ":"); + scc_ir_dump_type_linear(ctx, node->type); } } -// 线性输出节点信息(SSA IR风格) void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref) { scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref); - if (node == null) { - LOG_ERROR("invalid node ref"); + if (!node) { + scc_tree_dump_append(ctx->dump_ctx, "\n"); return; } - static char buff[512]; // 更大的缓冲区处理复杂的指令 - char *p = buff; - usize remaining = sizeof(buff); - - // 判断是否需要输出等号 cbool needs_equals = (node->tag != SCC_IR_VALUE_TAG_BRANCH && node->tag != SCC_IR_VALUE_TAG_JUMP && node->tag != SCC_IR_VALUE_TAG_RET && node->tag != SCC_IR_VALUE_TAG_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); + format_node_ref_or_value(ctx, node_ref); + scc_tree_dump_append(ctx->dump_ctx, " = "); } - // 构建操作部分 switch (node->tag) { case SCC_IR_VALUE_TAG_CONST_INT: - // 常量节点定义,直接输出值 - p += scc_snprintf(p, remaining, "%d", node->data.const_int.int32); + // 值已经在 format 中输出,这里不需要再做 break; - case SCC_IR_VALUE_TAG_CONST_UINT: + case SCC_IR_VALUE_TAG_CONST_UINT: { scc_ir_type_t *type = scc_ir_module_get_type(GET_MODULE(ctx), node->type); Assert(type != null); if (type->tag == SCC_IR_TYPE_u8) { - p += scc_snprintf(p, remaining, "%c", node->data.const_uint.uint8); + scc_tree_dump_append_fmt(ctx->dump_ctx, "%c", + node->data.const_uint.uint8); } else { - p += scc_snprintf(p, remaining, "%u", node->data.const_uint.uint32); + scc_tree_dump_append_fmt(ctx->dump_ctx, "%u", + node->data.const_uint.uint32); } break; + } case SCC_IR_VALUE_TAG_CONST_FLOAT: - p += scc_snprintf(p, remaining, "%f", node->data.const_float.float32); + scc_tree_dump_append_fmt(ctx->dump_ctx, "%f", + node->data.const_float.float32); break; - case SCC_IR_VALUE_TAG_AGGREGATE: + // 聚合类型:递归输出每个元素(每个占一行) scc_vec_foreach(node->data.aggregate.elements, i) { - scc_ir_value_ref_t elem_node = - scc_vec_at(node->data.aggregate.elements, i); - scc_ir_dump_node_linear(ctx, elem_node); - PRINT_NODE(ctx->dump_ctx, "\n"); + scc_ir_dump_node_linear( + ctx, scc_vec_at(node->data.aggregate.elements, i)); + scc_tree_dump_append(ctx->dump_ctx, "\n"); } return; - case SCC_IR_VALUE_TAG_ALLOC: - p += scc_snprintf(p, remaining, "alloc"); + scc_tree_dump_append(ctx->dump_ctx, "alloc"); break; - - case SCC_IR_VALUE_TAG_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); + case SCC_IR_VALUE_TAG_LOAD: + scc_tree_dump_append(ctx->dump_ctx, "load "); + format_node_ref_or_value(ctx, node->data.load.target); break; - } - - case SCC_IR_VALUE_TAG_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); + case SCC_IR_VALUE_TAG_STORE: + scc_tree_dump_append(ctx->dump_ctx, "store "); + format_node_ref_or_value(ctx, node->data.store.value); + scc_tree_dump_append(ctx->dump_ctx, " -> "); + format_node_ref_or_value(ctx, node->data.store.target); break; - } - case SCC_IR_VALUE_TAG_GET_ELEM_PTR: - case SCC_IR_VALUE_TAG_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, "%s %s, %s", - node->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr" - : "getelemptr", - src_buf, idx_buf); + case SCC_IR_VALUE_TAG_GET_PTR: + scc_tree_dump_append( + ctx->dump_ctx, + node->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr " : "getelemptr "); + format_node_ref_or_value(ctx, node->data.get_ptr.src_addr); + scc_tree_dump_append(ctx->dump_ctx, ", "); + format_node_ref_or_value(ctx, node->data.get_ptr.index); break; - } - - case SCC_IR_VALUE_TAG_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); + case SCC_IR_VALUE_TAG_OP: + format_node_ref_or_value(ctx, node->data.op.lhs); + scc_tree_dump_append_fmt(ctx->dump_ctx, " %s ", + get_op_str(node->data.op.op)); + format_node_ref_or_value(ctx, node->data.op.rhs); break; - } - case SCC_IR_VALUE_TAG_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 %%L%u, label %%L%u", - cond_buf, node->data.branch.true_bblock, - node->data.branch.false_bblock); + scc_tree_dump_append(ctx->dump_ctx, "br "); + format_node_ref_or_value(ctx, node->data.branch.cond); + scc_tree_dump_append_fmt( + ctx->dump_ctx, ", label %%L%u, label %%L%u", + node->data.branch.true_bblock, node->data.branch.false_bblock); } else { - p += scc_snprintf(p, remaining, "br label %%L%u", - node->data.branch.true_bblock); + scc_tree_dump_append_fmt(ctx->dump_ctx, "br label %%L%u", + node->data.branch.true_bblock); } break; - case SCC_IR_VALUE_TAG_JUMP: - p += scc_snprintf(p, remaining, "jmp label %%%u", - node->data.jump.target_bblock); + scc_tree_dump_append_fmt(ctx->dump_ctx, "jmp label %%%u", + node->data.jump.target_bblock); break; - case SCC_IR_VALUE_TAG_CALL: { - char node_name[256] = {0}; - char args_buf[256] = {0}; - 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); - } - scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), node->data.call.callee); - p += scc_snprintf(p, remaining, "call @%s(%s)", - func ? func->name : null, args_buf); + scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(", + func ? (func->name ? func->name : "") + : ""); + for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) { + if (i > 0) + scc_tree_dump_append(ctx->dump_ctx, ", "); + format_node_ref_or_value(ctx, scc_vec_at(node->data.call.args, i)); + } + scc_tree_dump_append(ctx->dump_ctx, ")"); break; } - case SCC_IR_VALUE_TAG_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); + scc_tree_dump_append(ctx->dump_ctx, "ret "); + format_node_ref_or_value(ctx, node->data.ret.ret_val); } else { - p += scc_snprintf(p, remaining, "ret void"); + scc_tree_dump_append(ctx->dump_ctx, "ret void"); } break; - - case SCC_IR_VALUE_TAG_FUNC_ARG_REF: { - p += scc_snprintf(p, remaining, "arg[%zu]", node->data.arg_ref.idx); + case SCC_IR_VALUE_TAG_FUNC_ARG_REF: + scc_tree_dump_append_fmt(ctx->dump_ctx, "arg[%zu]", + node->data.arg_ref.idx); break; - } - - case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: { - scc_snprintf(p, remaining, "global %s\n", node->name); - PRINT_NODE(ctx->dump_ctx, buff); + case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: + scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s\n", node->name); scc_ir_dump_node_linear(ctx, node->data.global_alloc.value); return; - } - - case SCC_IR_VALUE_TAG_CONST_ARRAY: { - PRINT_NODE(ctx->dump_ctx, "const_array "); + case SCC_IR_VALUE_TAG_CONST_ARRAY: + scc_tree_dump_append(ctx->dump_ctx, "const_array "); scc_ir_dump_type_linear(ctx, node->data.const_array.base_type); - PRINT_NODE(ctx->dump_ctx, " ["); + scc_tree_dump_append(ctx->dump_ctx, " ["); scc_vec_foreach(node->data.const_array.elements, i) { u8 ch = scc_vec_at(node->data.const_array.elements, i); - p += scc_snprintf(p, remaining, " `%c`, ", ch ? ch : ' '); - remaining = sizeof(buff) - (p - buff); + scc_tree_dump_append_fmt(ctx->dump_ctx, " `%c`, ", ch ? ch : ' '); } - p += scc_snprintf(p, remaining, " ]\n"); + scc_tree_dump_append(ctx->dump_ctx, " ]"); break; - } - default: - p += scc_snprintf(p, remaining, "<%s node %u>\n", - get_node_type_str(node->tag), node_ref); + scc_tree_dump_append_fmt(ctx->dump_ctx, "<%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_module_get_bblock(GET_MODULE(ctx), bblock_ref); - - if (bblock == null) { - PRINT_NODE(ctx->dump_ctx, "\n"); + if (!bblock) { + scc_tree_dump_append(ctx->dump_ctx, "\n"); return; } + if (bblock->label && bblock->label[0] != '\0') + scc_tree_dump_append_fmt(ctx->dump_ctx, "%%L%d %s:", bblock_ref, + bblock->label); + else + scc_tree_dump_append_fmt(ctx->dump_ctx, "%%L%d :", bblock_ref); - // 打印基本块标签 - static char label_buff[128]; - if (bblock->label && bblock->label[0] != '\0') { - scc_snprintf(label_buff, sizeof(label_buff), "%%L%d %s:", bblock_ref, - bblock->label); - } else { - scc_snprintf(label_buff, sizeof(label_buff), - "%%L%d :", bblock_ref); - } - PRINT_NODE(ctx->dump_ctx, label_buff); - - // 打印基本块中的每条指令 for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) { - scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i); - PRINT_NODE(ctx->dump_ctx, "\n "); - scc_ir_dump_node_linear(ctx, node_ref); + scc_tree_dump_append(ctx->dump_ctx, "\n "); + scc_ir_dump_node_linear(ctx, scc_vec_at(bblock->instrs, i)); } } -// 线性输出函数信息 void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref, int is_decl) { scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref); + scc_tree_dump_begin_line(ctx->dump_ctx); if (!func) { - LOG_ERROR("invalid function reference"); + scc_tree_dump_append(ctx->dump_ctx, "\n"); return; } + scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s", + (func->name && func->name[0]) ? func->name + : ""); - 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, "("); + scc_tree_dump_append(ctx->dump_ctx, "("); for (usize i = 0; i < scc_vec_size(func->params); i++) { if (i > 0) - PRINT_NODE(ctx->dump_ctx, ", "); + scc_tree_dump_append(ctx->dump_ctx, ", "); scc_ir_value_ref_t param_ref = scc_vec_at(func->params, i); - PRINT_NODE(ctx->dump_ctx, "%"); scc_ir_value_t *param_node = scc_ir_module_get_value(GET_MODULE(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); - } + 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); } - PRINT_NODE(ctx->dump_ctx, ")"); + scc_tree_dump_append(ctx->dump_ctx, ")"); } else { - PRINT_NODE(ctx->dump_ctx, "()"); + scc_tree_dump_append(ctx->dump_ctx, "()"); } - PRINT_NODE(ctx->dump_ctx, ": "); + scc_tree_dump_append(ctx->dump_ctx, ": "); scc_ir_dump_type_linear(ctx, func->type); if (is_decl) { - PRINT_NODE(ctx->dump_ctx, ";\n"); + scc_tree_dump_append(ctx->dump_ctx, ";\n"); return; } - PRINT_NODE(ctx->dump_ctx, " {\n"); - - // 打印基本块 + scc_tree_dump_append(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"); + scc_ir_dump_bblock_linear(ctx, scc_vec_at(func->bblocks, i)); + scc_tree_dump_append(ctx->dump_ctx, "\n"); } - - PRINT_NODE(ctx->dump_ctx, "}\n"); + scc_tree_dump_append(ctx->dump_ctx, "}\n"); } -// 线性输出整个程序 void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) { - scc_vec_foreach(ctx->cprog->global_vals, i) { - scc_ir_value_ref_t node_ref = scc_vec_at(ctx->cprog->global_vals, i); - scc_ir_dump_node_linear(ctx, node_ref); + for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) { + scc_ir_dump_node_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i)); } - scc_vec_foreach(ctx->cprog->func_decls, i) { + for (usize i = 0; i < scc_vec_size(ctx->cprog->func_decls); i++) { scc_ir_func_ref_t func_decl = scc_vec_at(ctx->cprog->func_decls, i); scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_decl); - Assert(func != null); - if (scc_vec_size(func->bblocks) == 0) - scc_ir_dump_func_linear(ctx, func_decl, true); + if (func && scc_vec_size(func->bblocks) == 0) + scc_ir_dump_func_linear(ctx, func_decl, 1); } - scc_vec_foreach(ctx->cprog->func_defs, i) { - scc_ir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i), - false); + for (usize i = 0; i < scc_vec_size(ctx->cprog->func_defs); i++) { + scc_ir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i), 0); } } diff --git a/libs/ir2mcode/include/reg_alloc.h b/libs/ir2mcode/include/reg_alloc.h index 40bac2d..b0c54f6 100644 --- a/libs/ir2mcode/include/reg_alloc.h +++ b/libs/ir2mcode/include/reg_alloc.h @@ -8,11 +8,12 @@ typedef enum { SCC_REG_KIND_UNDEF, SCC_REG_KIND_FUNC_ARG, - SCC_REG_KIND_GPR, ///< 通用寄存器(整数) - SCC_REG_KIND_FPR, ///< 浮点数寄存器 - SCC_REG_KIND_STACK, ///< 栈 - SCC_REG_KIND_IMM, ///< 整数立即数 - SCC_REG_KIND_IMM_FP, ///< 浮点数常量 + SCC_REG_KIND_GPR, ///< 通用寄存器(整数) + SCC_REG_KIND_FPR, ///< 浮点数寄存器 + SCC_REG_KIND_STACK, ///< 栈 + SCC_REG_KIND_STACK_ADDR, ///< 栈地址(如 alloc 节点) + SCC_REG_KIND_IMM, ///< 整数立即数 + SCC_REG_KIND_IMM_FP, ///< 浮点数常量 } scc_reg_kind_t; typedef struct { diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index 26d42e7..cb27a58 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -5,6 +5,24 @@ #define GET_MODULE(ctx) (&(ctx->cprog->module)) +static int scc_type_width(scc_ir_type_t *type) { + /* clang-format off */ + switch (type->tag) { + case SCC_IR_TYPE_i8: case SCC_IR_TYPE_u8: return 1; + case SCC_IR_TYPE_i16: case SCC_IR_TYPE_u16: return 2; + case SCC_IR_TYPE_i32: case SCC_IR_TYPE_u32: return 4; + case SCC_IR_TYPE_i64: case SCC_IR_TYPE_u64: return 8; + case SCC_IR_TYPE_PTR: return 8; + default: return 8; // 默认64位 + } + /* clang-format on */ +} + +static bool scc_type_is_signed(scc_ir_type_t *type) { + return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 || + type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64); +} + static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, scc_ir_value_ref_t node_ref) { Assert(ctx != null && loc != null); @@ -40,11 +58,12 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, scc_reg_loc_t arg_loc; // arg_loc.kind = SCC_REG_KIND_FUNC_ARG; // arg_loc.idx = node->data.arg_ref.idx; - arg_loc.kind = SCC_REG_KIND_STACK; + arg_loc.kind = SCC_REG_KIND_STACK_ADDR; arg_loc.idx = 8 * node->data.arg_ref.idx; *loc = arg_loc; return; } + case SCC_IR_VALUE_TAG_ALLOC: default: idx = (usize)scc_hashtable_get(ctx->noderef2regloc, (void *)(usize)node_ref); @@ -72,6 +91,12 @@ static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) { case SCC_REG_KIND_IMM: scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32 break; + case SCC_REG_KIND_STACK_ADDR: + // 将栈地址加载到寄存器(取地址) + // FIXME -8 for rdp + scc_mcode_amd64_lea_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP, + -loc->idx - 8); + break; default: LOG_FATAL("unsupported location"); } @@ -93,6 +118,12 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, case SCC_REG_KIND_IMM: LOG_FATAL("cannot store to immediate"); break; + case SCC_REG_KIND_STACK_ADDR: + // 将寄存器的值存储到栈地址 + // FIXME -8 for rdp + scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8, + reg); + break; default: LOG_FATAL("unsupported location"); break; @@ -123,8 +154,9 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, ///< ABI break; case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用 - case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack) - case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss) + break; + case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack) + case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss break; ///< 加载数据 case SCC_IR_VALUE_TAG_LOAD: { @@ -133,18 +165,79 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, scc_reg_loc_t to; parse_location(ctx, &from, node->data.load.target); parse_location(ctx, &to, node_ref); - load_value_to_reg(&ctx->sect_mcode, &from, SCC_AMD64_RAX); + + load_value_to_reg(&ctx->sect_mcode, &from, SCC_AMD64_RCX); + // 获取基类型宽度 + scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value( + GET_MODULE(ctx), node->data.load.target); + scc_ir_type_t *base_type = scc_ir_module_get_type( + GET_MODULE(ctx), ptr_type->data.pointer.base); + int width = scc_type_width(base_type); + bool is_signed = scc_type_is_signed(base_type); + + // 间接加载到 RAX + if (width == 1) { + if (is_signed) + scc_mcode_amd64_movsx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + else + scc_mcode_amd64_movzx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + } else if (width == 2) { + if (is_signed) + scc_mcode_amd64_movsx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + else + scc_mcode_amd64_movzx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + } else if (width == 4) { + if (is_signed) + scc_mcode_amd64_movsx_r64_m32(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + else + scc_mcode_amd64_mov_r32_m32( + &ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); // 32位加载自动清零高位 + } else { // 8 + scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + } + // 存储结果 store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX); break; } - ///< 存储数据 + ///< 存储数据 case SCC_IR_VALUE_TAG_STORE: { - scc_reg_loc_t from; - scc_reg_loc_t to; - parse_location(ctx, &from, node->data.store.value); - parse_location(ctx, &to, node->data.store.target); - load_value_to_reg(&ctx->sect_mcode, &from, SCC_AMD64_RAX); - store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX); + scc_reg_loc_t val_loc, addr_loc; + parse_location(ctx, &val_loc, node->data.store.value); + parse_location(ctx, &addr_loc, node->data.store.target); + + // 将值加载到 RAX + load_value_to_reg(&ctx->sect_mcode, &val_loc, SCC_AMD64_RAX); + // 将目标地址加载到 RCX + load_value_to_reg(&ctx->sect_mcode, &addr_loc, SCC_AMD64_RCX); + + // 获取目标指针的基类型宽度 + scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value( + GET_MODULE(ctx), node->data.store.target); + scc_ir_type_t *base_type = scc_ir_module_get_type( + GET_MODULE(ctx), ptr_type->data.pointer.base); + int width = scc_type_width(base_type); + + // 根据宽度生成存储指令 + if (width == 1) { + scc_mcode_amd64_mov_m8_r8(&ctx->sect_mcode, SCC_AMD64_RCX, + SCC_AMD64_RAX); + } else if (width == 2) { + scc_mcode_amd64_mov_m16_r16(&ctx->sect_mcode, SCC_AMD64_RCX, + SCC_AMD64_RAX); + } else if (width == 4) { + scc_mcode_amd64_mov_m32_r32(&ctx->sect_mcode, SCC_AMD64_RCX, + SCC_AMD64_RAX); + } else { // width == 8 + scc_mcode_amd64_mov_m64_r64(&ctx->sect_mcode, SCC_AMD64_RCX, + SCC_AMD64_RAX); + } break; } ///< 获取指针 @@ -189,6 +282,9 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, // 将右操作数加载到 RCX load_value_to_reg(&ctx->sect_mcode, &loc_rhs, SCC_AMD64_RCX); switch (node->data.op.op) { + case SCC_IR_OP_EMPTY: + Panic("unsupported empty op"); + break; case SCC_IR_OP_ADD: scc_mcode_amd64_add_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); @@ -200,16 +296,30 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, case SCC_IR_OP_MUL: scc_mcode_amd64_mul_r64(&ctx->sect_mcode, SCC_AMD64_RCX); break; - // [SCC_IR_OP_EMPTY] = "empty", [SCC_IR_OP_NEQ] = "!=", - // [SCC_IR_OP_EQ] = "==", [SCC_IR_OP_GT] = ">", - // [SCC_IR_OP_LT] = "<", [SCC_IR_OP_GE] = ">=", - // [SCC_IR_OP_LE] = "<=", [SCC_IR_OP_ADD] = "+", - // [SCC_IR_OP_SUB] = "-", [SCC_IR_OP_MUL] = "*", - // [SCC_IR_OP_DIV] = "/", [SCC_IR_OP_MOD] = "%", - // [SCC_IR_OP_AND] = "&", [SCC_IR_OP_OR] = "|", - // [SCC_IR_OP_XOR] = "^", [SCC_IR_OP_NOT] = "~", - // [SCC_IR_OP_SHL] = "<<", [SCC_IR_OP_SHR] = ">>", - // [SCC_IR_OP_SAR] = ">>a", // Arithmetic shift right + case SCC_IR_OP_DIV: + case SCC_IR_OP_MOD: + TODO(); + break; + case SCC_IR_OP_AND: + scc_mcode_amd64_and_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + break; + case SCC_IR_OP_OR: + scc_mcode_amd64_or_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + break; + case SCC_IR_OP_XOR: + scc_mcode_amd64_xor_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, + SCC_AMD64_RCX); + break; + case SCC_IR_OP_NOT: + scc_mcode_amd64_not_r64(&ctx->sect_mcode, SCC_AMD64_RAX); + break; + case SCC_IR_OP_SHL: + case SCC_IR_OP_SHR: + case SCC_IR_OP_SAR: + TODO(); + break; case SCC_IR_OP_NEQ: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); @@ -329,7 +439,12 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, return; } - scc_mcode_amd64_call_rel32(&ctx->sect_mcode, 0); + // FIXME hack func value + if (scc_vec_size(func->bblocks)) { + scc_mcode_amd64_call_rel32(&ctx->sect_mcode, 0); + } else { + scc_mcode_amd64_call_mem_rip_rel32(&ctx->sect_mcode, 0); + } usize sym_idx = sccf_builder_get_symbol_idx(ctx->builder, func->name); Assert(sym_idx != 0); sccf_builder_add_reloc( diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c index af4df14..68a0295 100644 --- a/libs/ir2mcode/src/reg_alloc.c +++ b/libs/ir2mcode/src/reg_alloc.c @@ -49,8 +49,7 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, case SCC_IR_VALUE_TAG_LOAD: case SCC_IR_VALUE_TAG_OP: case SCC_IR_VALUE_TAG_GET_PTR: - case SCC_IR_VALUE_TAG_GET_ELEM_PTR: - case SCC_IR_VALUE_TAG_ALLOC: { + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: { loc.kind = SCC_REG_KIND_STACK; loc.idx = ctx->alloc_stack_size; @@ -61,6 +60,20 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, (void *)scc_vec_size(ctx->reg_loc_vec)); break; } + case SCC_IR_VALUE_TAG_ALLOC: { + // 为 alloc 分配栈偏移,但不作为普通值存储 + loc.kind = + SCC_REG_KIND_STACK_ADDR; // 实际不需要存储到 reg_loc_vec + loc.idx = ctx->alloc_stack_size; + ctx->alloc_stack_size += 8; // 根据类型大小调整 + + // 记录偏移 + scc_vec_push(ctx->reg_loc_vec, loc); + scc_hashtable_set(&ctx->node_ref2reg_loc, + (void *)(usize)node_ref, + (void *)scc_vec_size(ctx->reg_loc_vec)); + break; + } case SCC_IR_VALUE_TAG_CALL: { // 处理返回值 scc_ir_type_t *func_type = diff --git a/libs/lexer/include/scc_lexer_token.h b/libs/lexer/include/scc_lexer_token.h index ca81d2a..f9d4a6a 100644 --- a/libs/lexer/include/scc_lexer_token.h +++ b/libs/lexer/include/scc_lexer_token.h @@ -185,7 +185,7 @@ typedef enum scc_tok_subtype { */ struct scc_lexer_token { scc_tok_type_t type; - scc_cstring_t lexeme; + scc_str_t lexeme; scc_pos_t loc; }; @@ -199,7 +199,7 @@ static inline void scc_lexer_tok_drop(scc_lexer_tok_t *tok) { tok->loc.line = 0; tok->loc.name = null; tok->loc.offset = 0; - scc_cstring_free(&tok->lexeme); + scc_str_drop(&tok->lexeme); } static inline cbool scc_lexer_tok_match(const scc_lexer_tok_t *tok, @@ -211,7 +211,7 @@ static inline cbool scc_lexer_tok_match(const scc_lexer_tok_t *tok, static inline scc_lexer_tok_t scc_lexer_tok_copy(const scc_lexer_tok_t *src) { Assert(src != null); scc_lexer_tok_t dst = *src; - dst.lexeme = scc_cstring_copy(&src->lexeme); + dst.lexeme = scc_str_copy(&src->lexeme); return dst; } diff --git a/libs/lexer/include/scc_lexer_utils.h b/libs/lexer/include/scc_lexer_utils.h index b9fd30b..e8becc5 100644 --- a/libs/lexer/include/scc_lexer_utils.h +++ b/libs/lexer/include/scc_lexer_utils.h @@ -6,13 +6,13 @@ static inline void scc_lexer_gen_number_true(scc_lexer_tok_t *tok) { Assert(tok != null && tok->type == SCC_TOK_UNKNOWN); tok->type = SCC_TOK_INT_LITERAL; - tok->lexeme = scc_cstring_from_cstr("1"); + tok->lexeme = scc_str_from_cstr("1"); } static inline void scc_lexer_gen_number_false(scc_lexer_tok_t *tok) { Assert(tok != null && tok->type == SCC_TOK_UNKNOWN); tok->type = SCC_TOK_INT_LITERAL; - tok->lexeme = scc_cstring_from_cstr("0"); + tok->lexeme = scc_str_from_cstr("0"); } static inline cbool scc_lexer_peek_non_blank(scc_lexer_tok_ring_t *stream, diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 862ab9b..2edbf10 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -74,13 +74,13 @@ static inline cbool peek_char(scc_lexer_t *lexer, scc_sstream_char_t *out) { } /* 从环形缓冲区消费一个字符,并将它追加到lexeme中 */ -static inline cbool next_char(scc_lexer_t *lexer, scc_cstring_t *lexeme, +static inline cbool next_char(scc_lexer_t *lexer, scc_str_t *lexeme, scc_sstream_char_t *out) { cbool ok; scc_ring_next(*lexer->stream_ref, *out, ok); if (!ok) return false; - scc_cstring_append_ch(lexeme, out->character); + scc_str_append_ch(lexeme, out->character); return true; } @@ -88,7 +88,7 @@ static inline cbool next_char(scc_lexer_t *lexer, scc_cstring_t *lexeme, void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { scc_sstream_char_t cur = {0}; - scc_cstring_t lex = scc_cstring_create(); // 临时lexeme + scc_str_t lex = scc_str_empty(); // 临时lexeme // 尝试预览第一个字符 if (!peek_char(lexer, &cur)) { @@ -165,7 +165,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { scc_ring_consume(*lexer->stream_ref); } // 检查是否为关键字 - int idx = keyword_cmp(scc_cstring_as_cstr(&lex), scc_cstring_len(&lex)); + int idx = keyword_cmp(scc_str_as_cstr(&lex), scc_str_len(&lex)); if (idx != -1) { token->type = keywords[idx].tok_type; } @@ -478,8 +478,8 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { token->loc = start_loc; token->lexeme = lex; // 转移所有权 LEX_DEBUG("get token `%s` (%s) at %s:%d:%d", scc_get_tok_name(token->type), - scc_cstring_as_cstr(&token->lexeme), token->loc.name, - token->loc.line, token->loc.col); + scc_str_as_cstr(&token->lexeme), token->loc.name, token->loc.line, + token->loc.col); } // scc_lexer_get_token maybe got invalid (with parser) diff --git a/libs/lexer/src/main.c b/libs/lexer/src/main.c index 60a51aa..551edee 100644 --- a/libs/lexer/src/main.c +++ b/libs/lexer/src/main.c @@ -58,10 +58,9 @@ int main(int argc, char *argv[]) { } LOG_INFO("get token [%-8s] `%s` at %s:%d:%d", - scc_get_tok_name(token.type), - scc_cstring_as_cstr(&token.lexeme), token.loc.name, - token.loc.line, token.loc.col); - scc_cstring_free(&token.lexeme); + scc_get_tok_name(token.type), scc_str_as_cstr(&token.lexeme), + token.loc.name, token.loc.line, token.loc.col); + scc_str_drop(&token.lexeme); } scc_sstream_drop_ring(ref); scc_sstream_drop(&stream); diff --git a/libs/lexer/tests/test_lexer.c b/libs/lexer/tests/test_lexer.c index ef60db1..7d17272 100644 --- a/libs/lexer/tests/test_lexer.c +++ b/libs/lexer/tests/test_lexer.c @@ -4,7 +4,7 @@ #include // 辅助函数:释放 token 的 lexeme -static void free_token(scc_lexer_tok_t *tok) { scc_cstring_free(&tok->lexeme); } +static void free_token(scc_lexer_tok_t *tok) { scc_str_drop(&tok->lexeme); } // 单 token 测试宏(检查类型) #define TEST_TOKEN(input, expected_type) \ @@ -18,12 +18,11 @@ static void free_token(scc_lexer_tok_t *tok) { scc_cstring_free(&tok->lexeme); } scc_lexer_get_token(&lexer, &token); \ \ TEST_CHECK(token.type == expected_type && \ - scc_strcmp(input, scc_cstring_as_cstr(&token.lexeme)) == \ - 0); \ + scc_strcmp(input, scc_str_as_cstr(&token.lexeme)) == 0); \ TEST_MSG("Input: '%s'", input); \ TEST_MSG("Expected: %s `%s`", scc_get_tok_name(expected_type), input); \ TEST_MSG("Got: %s `%s`", scc_get_tok_name(token.type), \ - scc_cstring_as_cstr(&token.lexeme)); \ + scc_str_as_cstr(&token.lexeme)); \ \ free_token(&token); \ scc_sstream_drop_ring(ref); \ diff --git a/libs/parser/src/parse_decl.c b/libs/parser/src/parse_decl.c index 4e37d33..6799b04 100644 --- a/libs/parser/src/parse_decl.c +++ b/libs/parser/src/parse_decl.c @@ -204,8 +204,8 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser, scc_parser_next_consume(parser, &tok); lhs = scc_malloc(sizeof(scc_ast_expr_t)); Assert(lhs != null); - scc_ast_expr_member_init( - lhs, ptr, scc_cstring_as_cstr(&tok.lexeme), tok.loc); + scc_ast_expr_member_init(lhs, ptr, scc_str_as_cstr(&tok.lexeme), + tok.loc); if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) { ptr = lhs; continue; diff --git a/libs/parser/src/parse_expr.c b/libs/parser/src/parse_expr.c index 07dd65f..c4ccb79 100644 --- a/libs/parser/src/parse_expr.c +++ b/libs/parser/src/parse_expr.c @@ -728,7 +728,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) { parser_sync(parser); return null; } - const char *name = scc_cstring_as_cstr(&ident_tok.lexeme); + const char *name = scc_str_as_cstr(&ident_tok.lexeme); scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t)); Assert(member != null); @@ -786,7 +786,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return null; expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme), + scc_ast_expr_identifier_init(expr, scc_str_as_cstr(&tok.lexeme), tok.loc); break; } @@ -795,8 +795,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return null; expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme), - false, tok.loc); + scc_ast_expr_literal_int_init(expr, scc_str_as_cstr(&tok.lexeme), false, + tok.loc); break; } case SCC_TOK_FLOAT_LITERAL: { @@ -804,7 +804,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return null; expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme), + scc_ast_expr_literal_float_init(expr, scc_str_as_cstr(&tok.lexeme), false, tok.loc); break; } @@ -813,12 +813,12 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { return null; expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); - scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme), + scc_ast_expr_literal_char_init(expr, scc_str_as_cstr(&tok.lexeme), false, tok.loc); break; } case SCC_TOK_STRING_LITERAL: { - scc_cstring_t string = scc_cstring_create(); + scc_str_t string = scc_str_empty(); scc_lexer_tok_t tok; while (1) { tok_ptr = scc_parser_peek(parser); @@ -829,16 +829,16 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) { break; } scc_parser_next_consume(parser, &tok); - scc_cstring_t tmp = scc_cstring_move(&tok.lexeme); + scc_str_t tmp = scc_str_move(&tok.lexeme); scc_lexer_tok_drop(&tok); - scc_cstring_append(&string, &tmp); + scc_str_append(&string, &tmp); } expr = scc_malloc(sizeof(scc_ast_expr_t)); Assert(expr != null); // FIXME loc - scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string), - true, tok.loc); + scc_ast_expr_literal_string_init(expr, scc_str_as_cstr(&string), true, + tok.loc); break; } case SCC_TOK_L_PAREN: diff --git a/libs/parser/src/parse_stmt.c b/libs/parser/src/parse_stmt.c index db8db2b..a8c9ceb 100644 --- a/libs/parser/src/parse_stmt.c +++ b/libs/parser/src/parse_stmt.c @@ -92,8 +92,7 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser, scc_ast_stmt_t *stmt = ast_stmt_alloc(); Assert(stmt != null); - scc_ast_stmt_label_init(stmt, scc_cstring_as_cstr(&tok.lexeme), statement, - pos); + scc_ast_stmt_label_init(stmt, scc_str_as_cstr(&tok.lexeme), statement, pos); return stmt; } @@ -312,7 +311,7 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser, if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) { scc_lexer_tok_t tok = {0}; if (scc_parser_next_consume(parser, &tok)) { - scc_ast_stmt_goto_init(stmt, scc_cstring_as_cstr(&tok.lexeme), pos); + scc_ast_stmt_goto_init(stmt, scc_str_as_cstr(&tok.lexeme), pos); } else { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected label after goto."); diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index 94b2ea7..2c4049b 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -229,8 +229,8 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) { return true; // typedef 名称(标识符也可能是类型说明符) case SCC_TOK_IDENT: - return scc_parse_got_type( - parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null; + return scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme)) != + null; default: return false; } @@ -260,8 +260,8 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) { // typedef 名称 case SCC_TOK_IDENT: // 需要检查标识符是否在符号表中定义为 typedef - return scc_parse_got_type( - parser, scc_cstring_as_cstr(&tok_ptr->lexeme)) != null; + return scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme)) != + null; default: return false; } @@ -585,7 +585,7 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser, if (tok_ptr->type == SCC_TOK_IDENT) { scc_parser_next_consume(parser, &tok); - name = scc_cstring_as_cstr(&tok.lexeme); + name = scc_str_as_cstr(&tok.lexeme); tok_ptr = scc_parser_peek(parser); } @@ -683,7 +683,7 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { if (tok_ptr->type == SCC_TOK_IDENT) { scc_parser_next_consume(parser, &tok); tok_ptr = scc_parser_peek(parser); - name = scc_cstring_as_cstr(&tok.lexeme); + name = scc_str_as_cstr(&tok.lexeme); } if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) { @@ -711,8 +711,8 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) { scc_ast_decl_t *enum_item_decl = scc_malloc(sizeof(scc_ast_decl_t)); Assert(enum_item_decl != null); scc_ast_decl_val_init(enum_item_decl, type, - scc_cstring_as_cstr(&tok.lexeme), - enum_item_init, tok.loc); + scc_str_as_cstr(&tok.lexeme), enum_item_init, + tok.loc); scc_vec_push(member, enum_item_decl); tok_ptr = scc_parser_peek(parser); @@ -777,11 +777,11 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) { goto done; case SCC_TOK_IDENT: info.user_type = - scc_parse_got_type(parser, scc_cstring_as_cstr(&tok_ptr->lexeme)); + scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme)); if (info.user_type == null) { SCC_ERROR(scc_parser_got_current_pos(parser), "Expected type specifier %s", - scc_cstring_as_cstr(&tok_ptr->lexeme)); + scc_str_as_cstr(&tok_ptr->lexeme)); } scc_parser_next_consume(parser, null); Assert(info.user_type != null); @@ -1217,7 +1217,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser, // FIXME memory leak const char *name = decl_name_tok.type == SCC_TOK_IDENT - ? scc_cstring_as_cstr(&decl_name_tok.lexeme) + ? scc_str_as_cstr(&decl_name_tok.lexeme) : null; if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) { diff --git a/libs/parser/src/scc_sema.c b/libs/parser/src/scc_sema.c index 7d033fa..f07ee67 100644 --- a/libs/parser/src/scc_sema.c +++ b/libs/parser/src/scc_sema.c @@ -77,31 +77,31 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type, if (node_type == SCC_AST_DECL_STRUCT) { scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc); // FIXME memory leak - scc_cstring_t name = scc_cstring_from_cstr("$S_"); + scc_str_t name = scc_str_from_cstr("$S_"); if (decl->name == null) { decl->name = ""; } - scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), + scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); + scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), &type->base); } else if (node_type == SCC_AST_DECL_UNION) { scc_ast_type_union_init(type, decl->name, decl, decl->base.loc); - scc_cstring_t name = scc_cstring_from_cstr("$U_"); + scc_str_t name = scc_str_from_cstr("$U_"); if (decl->name == null) { decl->name = ""; } - scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), + scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); + scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), &type->base); } else if (node_type == SCC_AST_DECL_ENUM) { scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc); - scc_cstring_t name = scc_cstring_from_cstr("$E_"); + scc_str_t name = scc_str_from_cstr("$E_"); if (decl->name == null) { decl->name = ""; } - scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); - scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), + scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name)); + scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name), &type->base); scc_vec_foreach(decl->record.fields, i) { diff --git a/libs/pproc/include/pproc_macro.h b/libs/pproc/include/pproc_macro.h index 1966019..067de4e 100644 --- a/libs/pproc/include/pproc_macro.h +++ b/libs/pproc/include/pproc_macro.h @@ -19,7 +19,7 @@ typedef enum { typedef SCC_VEC(scc_lexer_tok_vec_t) scc_pproc_macro_extened_params_t; // 宏定义结构 typedef struct scc_macro { - scc_cstring_t name; // 宏名称 + scc_str_t name; // 宏名称 scc_pproc_macro_type_t type; // 宏类型 scc_lexer_tok_vec_t replaces; // 替换列表 scc_lexer_tok_vec_t params; // 参数列表(仅函数宏) @@ -35,7 +35,7 @@ typedef struct scc_macro_table { * @param type 宏类型 * @return 创建的宏对象指针,失败返回NULL */ -scc_pproc_macro_t *scc_pproc_macro_new(const scc_cstring_t *name, +scc_pproc_macro_t *scc_pproc_macro_new(const scc_str_t *name, scc_pproc_macro_type_t type); /** @@ -52,7 +52,7 @@ void scc_pproc_macro_drop(scc_pproc_macro_t *macro); * @return 成功返回true,失败返回false */ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name, + const scc_str_t *name, const scc_lexer_tok_vec_t *replacement); /** @@ -64,7 +64,7 @@ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *pp, * @return 成功返回true,失败返回false */ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name, + const scc_str_t *name, const scc_lexer_tok_vec_t *params, const scc_lexer_tok_vec_t *replacement); /** @@ -84,7 +84,7 @@ scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp, * @return 找到的宏对象指针,未找到返回NULL */ scc_pproc_macro_t *scc_pproc_macro_table_get(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name); + const scc_str_t *name); /** * @brief 从预处理器中删除宏 @@ -93,7 +93,7 @@ scc_pproc_macro_t *scc_pproc_macro_table_get(scc_pproc_macro_table_t *pp, * @return 成功删除返回true,未找到返回false */ cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name); + const scc_str_t *name); void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros); void scc_pproc_macro_table_drop(scc_pproc_macro_table_t *macros); diff --git a/libs/pproc/include/scc_pproc.h b/libs/pproc/include/scc_pproc.h index 7caaacc..bfbda45 100644 --- a/libs/pproc/include/scc_pproc.h +++ b/libs/pproc/include/scc_pproc.h @@ -29,7 +29,7 @@ typedef struct { typedef SCC_VEC(scc_pproc_file_t *) scc_pproc_file_stack_t; typedef SCC_VEC(scc_lexer_tok_ring_t *) scc_pproc_ring_vec_t; -typedef SCC_VEC(scc_cstring_t) scc_pproc_cstr_vec_t; +typedef SCC_VEC(scc_str_t) scc_pproc_cstr_vec_t; typedef struct scc_pproc { scc_lexer_tok_ring_t *org_ring; @@ -61,13 +61,13 @@ scc_lexer_tok_ring_t *scc_pproc_to_ring(scc_pproc_t *pp, int ring_size, void scc_pproc_drop(scc_pproc_t *pp); static inline void scc_pproc_add_include_path(scc_pproc_t *pp, - const scc_cstring_t *path) { - scc_vec_push(pp->include_paths, scc_cstring_copy(path)); + const scc_str_t *path) { + scc_vec_push(pp->include_paths, scc_str_copy(path)); } static inline void scc_pproc_add_include_path_cstr(scc_pproc_t *pp, const char *path) { - scc_vec_push(pp->include_paths, scc_cstring_from_cstr(path)); + scc_vec_push(pp->include_paths, scc_str_from_cstr(path)); } void scc_pproc_handle_directive(scc_pproc_t *pp); diff --git a/libs/pproc/src/pproc_directive.c b/libs/pproc/src/pproc_directive.c index f7a15d8..a719c37 100644 --- a/libs/pproc/src/pproc_directive.c +++ b/libs/pproc/src/pproc_directive.c @@ -133,8 +133,8 @@ void scc_pproc_parse_function_macro(scc_pproc_t *pp, if (idx++ % 2 != 0) { LOG_FATAL("ERROR"); } - scc_cstring_t va_args = scc_cstring_from_cstr("__VA_ARGS__"); - scc_cstring_free(&arg->lexeme); + scc_str_t va_args = scc_str_from_cstr("__VA_ARGS__"); + scc_str_drop(&arg->lexeme); arg->lexeme = va_args; scc_vec_push(macro->params, *arg); } else if (scc_get_tok_subtype(arg->type) == @@ -249,12 +249,12 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { SCC_ERROR(tok.loc, "invalid preprocessing directive"); goto ERROR; } - int ret = keyword_cmp(scc_cstring_as_cstr(&tok.lexeme), - scc_cstring_len(&tok.lexeme)); + int ret = + keyword_cmp(scc_str_as_cstr(&tok.lexeme), scc_str_len(&tok.lexeme)); if (ret == -1) { scc_lexer_tok_drop(&tok); SCC_ERROR(tok.loc, "expected preprocessor directive name, got '%s'", - scc_cstring_as_cstr(&tok.lexeme)); + scc_str_as_cstr(&tok.lexeme)); goto ERROR; } scc_tok_type_t type = keywords[ret].tok_type; @@ -362,7 +362,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { return; \ } \ if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { \ - func_name(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme)); \ + func_name(tok.loc, "%s", scc_str_as_cstr(&tok.lexeme)); \ } \ scc_lexer_tok_drop(&tok); \ } \ @@ -382,6 +382,6 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { break; } ERROR: - LOG_WARN("Unhandled directive: %s", scc_cstring_as_cstr(&tok.lexeme)); + LOG_WARN("Unhandled directive: %s", scc_str_as_cstr(&tok.lexeme)); scc_lexer_skip_until_newline(pp->cur_ring); } diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index 6a02c1b..09b7ab1 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -18,8 +18,8 @@ static inline scc_lexer_tok_t scc_pproc_tok_copy(scc_pproc_expand_t *ctx, static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *arg_tokens) { // WRITE BY AI - scc_cstring_t str = scc_cstring_create(); - scc_cstring_append_ch(&str, '\"'); // 左引号 + scc_str_t str = scc_str_empty(); + scc_str_append_ch(&str, '\"'); // 左引号 int need_space = 0; // 是否需要插入空格 scc_lexer_tok_t *tok = null; @@ -32,7 +32,7 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, // 需要空格且当前不是第一个有效token,插入一个空格 if (need_space && i > 0) { - scc_cstring_append_ch(&str, ' '); + scc_str_append_ch(&str, ' '); } // 对字符串/字符常量内的 " 和 \ 进行转义 @@ -41,10 +41,10 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, // 注意:lex包含两端的引号,需要跳过首尾,转义内部字符 // 简化:暂不处理内部转义,直接追加 } - scc_cstring_append(&str, &tok->lexeme); + scc_str_append(&str, &tok->lexeme); need_space = 0; } - scc_cstring_append_ch(&str, '\"'); // 右引号 + scc_str_append_ch(&str, '\"'); // 右引号 scc_lexer_tok_t result; result.type = SCC_TOK_STRING_LITERAL; @@ -60,19 +60,19 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx, static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx, const scc_lexer_tok_t *left, const scc_lexer_tok_t *right) { - scc_cstring_t new_lex = scc_cstring_from_cstr(""); + scc_str_t new_lex = scc_str_from_cstr(""); if (left != null) { - scc_cstring_append(&new_lex, &left->lexeme); + scc_str_append(&new_lex, &left->lexeme); } if (right != null) { - scc_cstring_append(&new_lex, &right->lexeme); + scc_str_append(&new_lex, &right->lexeme); } scc_lexer_t lexer; scc_sstream_t sstream; // new_lex 所有权转移 - scc_sstream_init_by_buffer(&sstream, scc_cstring_as_cstr(&new_lex), - scc_cstring_len(&new_lex), true, 8); + scc_sstream_init_by_buffer(&sstream, scc_str_as_cstr(&new_lex), + scc_str_len(&new_lex), true, 8); scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream)); scc_lexer_tok_ring_t *ring = scc_lexer_to_ring(&lexer, 8, true); @@ -269,7 +269,7 @@ expand_arguments(scc_pproc_macro_extened_params_t *expanded_params, scc_vec_init(expanded_param); scc_vec_foreach(splite_param, j) { scc_lexer_tok_t tok = scc_vec_at(splite_param, j); - tok.lexeme = scc_cstring_copy(&tok.lexeme); + tok.lexeme = scc_str_copy(&tok.lexeme); scc_vec_push(expanded_param, tok); } scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(&expanded_param); @@ -353,8 +353,8 @@ RETURN: static int find_params(const scc_lexer_tok_t *tok, const scc_pproc_macro_t *macro) { scc_vec_foreach(macro->params, j) { - if (scc_cstring_cmp(&(tok->lexeme), - &(scc_vec_at(macro->params, j).lexeme)) == 0) { + if (scc_str_equal(&(tok->lexeme), + &(scc_vec_at(macro->params, j).lexeme)) == 0) { return j; } } @@ -437,8 +437,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx, scc_lexer_tok_t tok = scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i)); if (tok.type == SCC_TOK_BLANK) { - scc_cstring_free(&tok.lexeme); - tok.lexeme = scc_cstring_from_cstr(" "); + scc_str_drop(&tok.lexeme); + tok.lexeme = scc_str_from_cstr(" "); scc_vec_push(tok_buffer, tok); continue; } @@ -449,8 +449,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx, int right_idx = got_right_non_blank(i, ¯o->replaces); if (right_idx >= (int)macro->replaces.size) { LOG_WARN("generate empty stringify"); - scc_cstring_free(&tok.lexeme); - tok.lexeme = scc_cstring_from_cstr(""); + scc_str_drop(&tok.lexeme); + tok.lexeme = scc_str_from_cstr(""); scc_vec_push(tok_buffer, tok); break; } @@ -491,7 +491,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx, scc_vec_size(right_vec) ? &scc_vec_at(right_vec, 0) : null; // GNU ## extention - if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)), + if (scc_strcmp(scc_str_as_cstr(&(right_tok->lexeme)), "__VA_ARGS__") == 0) { if (scc_vec_size(right_vec) == 0) { concact(ctx, &tok_buffer, right, true); @@ -550,8 +550,8 @@ static inline void expand_object_macro(scc_pproc_expand_t *ctx, scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i)); if (tok.type == SCC_TOK_BLANK) { // FIXME using function to warpper it - scc_cstring_free(&tok.lexeme); - tok.lexeme = scc_cstring_from_cstr(" "); + scc_str_drop(&tok.lexeme); + tok.lexeme = scc_str_from_cstr(" "); } else if (tok.type == SCC_TOK_SHARP_SHARP) { // ## contact scc_lexer_tok_drop(&tok); @@ -635,7 +635,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { } if (expand_ctx->need_parse_defined && - scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) { + scc_strcmp(scc_str_as_cstr(&tok.lexeme), "defined") == 0) { scc_pos_t pos = tok.loc; scc_lexer_tok_drop(&tok); if (parse_defined(expand_ctx, &pos)) { @@ -679,19 +679,19 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { } // FIXME 这可能不符合c语义 case SCC_PP_MACRO_BUILTIN__FILE__: - scc_cstring_free(&tok.lexeme); - scc_cstring_append_ch(&tok.lexeme, '"'); - scc_cstring_append_cstr(&tok.lexeme, tok.loc.name, - scc_strlen(tok.loc.name)); - scc_cstring_append_ch(&tok.lexeme, '"'); + scc_str_drop(&tok.lexeme); + scc_str_append_ch(&tok.lexeme, '"'); + scc_str_append_cstr(&tok.lexeme, tok.loc.name, + scc_strlen(tok.loc.name)); + scc_str_append_ch(&tok.lexeme, '"'); tok.type = SCC_TOK_STRING_LITERAL; scc_vec_push(expand_ctx->output, tok); break; case SCC_PP_MACRO_BUILTIN__LINE__: - scc_cstring_free(&tok.lexeme); + scc_str_drop(&tok.lexeme); char *buff = scc_malloc(32); scc_snprintf(buff, 32, "%zu", tok.loc.line); - tok.lexeme = scc_cstring_from_cstr(buff); + tok.lexeme = scc_str_from_cstr(buff); scc_free(buff); tok.type = SCC_TOK_INT_LITERAL; scc_vec_push(expand_ctx->output, tok); diff --git a/libs/pproc/src/pproc_if.c b/libs/pproc/src/pproc_if.c index ae7a05e..30440c0 100644 --- a/libs/pproc/src/pproc_if.c +++ b/libs/pproc/src/pproc_if.c @@ -148,8 +148,8 @@ static int parse_constant_condition(scc_pproc_t *pp, if (tok.type == SCC_TOK_INT_LITERAL) { // got int - const char *intstr = scc_cstring_as_cstr(&tok.lexeme); - for (int i = scc_cstring_len(&tok.lexeme) - 1; i >= 0; i--) { + const char *intstr = scc_str_as_cstr(&tok.lexeme); + for (int i = scc_str_len(&tok.lexeme) - 1; i >= 0; i--) { res = res * 10 + intstr[i] - '0'; } } else { diff --git a/libs/pproc/src/pproc_include.c b/libs/pproc/src/pproc_include.c index 3a9f6ae..5f0aec8 100644 --- a/libs/pproc/src/pproc_include.c +++ b/libs/pproc/src/pproc_include.c @@ -2,9 +2,9 @@ #include #include -static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, - scc_pos_t *pos, int is_system) { - scc_cstring_t fpath = scc_cstring_create(); +static int switch_file_stack(scc_pproc_t *pp, scc_str_t *fname, scc_pos_t *pos, + int is_system) { + scc_str_t fpath = scc_str_empty(); int ret = 0; const char *org_fname = pos->name; @@ -12,10 +12,10 @@ static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, if (!is_system) { const char parent[] = "/../"; // FIXME maybe it can eazy - scc_cstring_append_cstr(&fpath, org_fname, scc_strlen(org_fname)); - scc_cstring_append_cstr(&fpath, parent, scc_strlen(parent)); - scc_cstring_append(&fpath, fname); - ret = scc_fexists(scc_cstring_as_cstr(&fpath)); + scc_str_append_cstr(&fpath, org_fname, scc_strlen(org_fname)); + scc_str_append_cstr(&fpath, parent, scc_strlen(parent)); + scc_str_append(&fpath, fname); + ret = scc_fexists(scc_str_as_cstr(&fpath)); if (ret == true) { goto FOPEN; } @@ -23,17 +23,17 @@ static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, /* system default path and -I includes path */ scc_vec_foreach(pp->include_paths, i) { - scc_cstring_free(&fpath); - scc_cstring_t *syspath = &scc_vec_at(pp->include_paths, i); - scc_cstring_append(&fpath, syspath); - scc_cstring_append_ch(&fpath, '/'); - scc_cstring_append(&fpath, fname); - ret = scc_fexists(scc_cstring_as_cstr(&fpath)); + scc_str_drop(&fpath); + scc_str_t *syspath = &scc_vec_at(pp->include_paths, i); + scc_str_append(&fpath, syspath); + scc_str_append_ch(&fpath, '/'); + scc_str_append(&fpath, fname); + ret = scc_fexists(scc_str_as_cstr(&fpath)); if (ret == true) { goto FOPEN; } } - SCC_ERROR(*pos, "include file '%s' not found", scc_cstring_as_cstr(fname)); + SCC_ERROR(*pos, "include file '%s' not found", scc_str_as_cstr(fname)); return -1; FOPEN: if ((int)scc_vec_size(pp->file_stack) >= pp->config.max_include_depth) { @@ -44,7 +44,7 @@ FOPEN: scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t)); Assert(file != null); - if (scc_sstream_init(&(file->sstream), scc_cstring_as_cstr(&fpath), 1024)) { + if (scc_sstream_init(&(file->sstream), scc_str_as_cstr(&fpath), 1024)) { return -1; } scc_lexer_init(&(file->lexer), scc_sstream_to_ring(&(file->sstream))); @@ -62,21 +62,21 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok, scc_pos_t pos = include_tok->loc; scc_lexer_tok_drop(include_tok); - scc_cstring_t line = scc_cstring_create(); + scc_str_t line = scc_str_empty(); while (1) { scc_ring_next_consume(*tok_ring, tok, ok); if (!ok) break; if (scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_EMPTYSPACE && scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_COMMENT) { - scc_cstring_append(&line, &tok.lexeme); + scc_str_append(&line, &tok.lexeme); } scc_lexer_tok_drop(&tok); } scc_ring_free(*tok_ring); - const char *includename = scc_cstring_as_cstr(&line); - int len = scc_cstring_len(&line); + const char *includename = scc_str_as_cstr(&line); + int len = scc_str_len(&line); if (len < 2) { goto ERROR; } else if (len == 2) { @@ -94,19 +94,19 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok, goto ERROR; } } - scc_cstring_t fname = scc_cstring_create(); + scc_str_t fname = scc_str_empty(); for (int i = 1; i < len - 1; i++) { - scc_cstring_append_ch(&fname, includename[i]); + scc_str_append_ch(&fname, includename[i]); } - scc_cstring_free(&line); + scc_str_drop(&line); int is_system = includename[0] == '<'; if (switch_file_stack(pp, &fname, &pos, is_system)) { // LOG_ERROR() } - scc_cstring_free(&fname); + scc_str_drop(&fname); return; ERROR: SCC_ERROR(pos, "invalid include filename, expected \"FILENAME\" or "); - scc_cstring_free(&line); + scc_str_drop(&line); } diff --git a/libs/pproc/src/pproc_macro.c b/libs/pproc/src/pproc_macro.c index 9cc085b..7eb5122 100644 --- a/libs/pproc/src/pproc_macro.c +++ b/libs/pproc/src/pproc_macro.c @@ -1,7 +1,7 @@ #include // 创建宏对象 -scc_pproc_macro_t *scc_pproc_macro_new(const scc_cstring_t *name, +scc_pproc_macro_t *scc_pproc_macro_new(const scc_str_t *name, scc_pproc_macro_type_t type) { scc_pproc_macro_t *macro = scc_malloc(sizeof(scc_pproc_macro_t)); if (!macro) { @@ -9,7 +9,7 @@ scc_pproc_macro_t *scc_pproc_macro_new(const scc_cstring_t *name, return null; } - macro->name = scc_cstring_copy(name); + macro->name = scc_str_copy(name); macro->type = type; scc_vec_init(macro->params); scc_vec_init(macro->replaces); @@ -34,14 +34,14 @@ void scc_pproc_macro_drop(scc_pproc_macro_t *macro) { } scc_vec_free(macro->replaces); - scc_cstring_free(¯o->name); + scc_str_drop(¯o->name); scc_free(macro); } // 添加对象宏 cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros, - const scc_cstring_t *name, + const scc_str_t *name, const scc_lexer_tok_vec_t *replacement) { if (!macros || !name || !replacement) return false; @@ -56,7 +56,7 @@ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros, scc_pproc_macro_t *existing = scc_hashtable_get(¯os->table, ¯o->name); if (existing) { - LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name)); + LOG_WARN("Redefining macro: %s", scc_str_as_cstr(¯o->name)); scc_pproc_macro_drop(existing); } @@ -66,7 +66,7 @@ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros, // 添加函数宏 cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros, - const scc_cstring_t *name, + const scc_str_t *name, const scc_lexer_tok_vec_t *params, const scc_lexer_tok_vec_t *replacement) { if (!macros || !name || !params || !replacement) @@ -84,7 +84,7 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros, scc_pproc_macro_t *existing = scc_hashtable_get(¯os->table, ¯o->name); if (existing) { - LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name)); + LOG_WARN("Redefining macro: %s", scc_str_as_cstr(¯o->name)); scc_pproc_macro_drop(existing); } @@ -96,10 +96,10 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros, scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp, scc_pproc_macro_t *macro) { - Assert(pp != null && macro != null && scc_cstring_len(¯o->name) != 0); + Assert(pp != null && macro != null && scc_str_len(¯o->name) != 0); scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, ¯o->name, macro); if (old && old != macro) { - LOG_WARN("same macro name `%s`", scc_cstring_as_cstr(¯o->name)); + LOG_WARN("same macro name `%s`", scc_str_as_cstr(¯o->name)); scc_pproc_macro_drop(old); } return macro; @@ -107,13 +107,13 @@ scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp, // 查找宏定义 scc_pproc_macro_t *scc_pproc_macro_table_get(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name) { + const scc_str_t *name) { return scc_hashtable_get(&pp->table, name); } // 从预处理器中删除宏 cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp, - const scc_cstring_t *name) { + const scc_str_t *name) { if (!pp || !name) return false; @@ -127,18 +127,18 @@ cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp, } static u32 hash_func(const void *key) { - const scc_cstring_t *string = (const scc_cstring_t *)key; - return scc_strhash32(scc_cstring_as_cstr(string)); + const scc_str_t *string = (const scc_str_t *)key; + return scc_strhash32(scc_str_as_cstr(string)); } static int hash_cmp(const void *key1, const void *key2) { - const scc_cstring_t *str1 = (const scc_cstring_t *)key1; - const scc_cstring_t *str2 = (const scc_cstring_t *)key2; + const scc_str_t *str1 = (const scc_str_t *)key1; + const scc_str_t *str2 = (const scc_str_t *)key2; if (str1->size != str2->size) { return str1->size - str2->size; } - return scc_strcmp(scc_cstring_as_cstr(str1), scc_cstring_as_cstr(str2)); + return scc_strcmp(scc_str_as_cstr(str1), scc_str_as_cstr(str2)); } void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros) { diff --git a/libs/pproc/src/scc_pproc.c b/libs/pproc/src/scc_pproc.c index a77d4c0..f03d0fb 100644 --- a/libs/pproc/src/scc_pproc.c +++ b/libs/pproc/src/scc_pproc.c @@ -110,8 +110,7 @@ void scc_pproc_add_builtin_macros(scc_pproc_macro_table_t *macro_table) { {"__LINE__", SCC_PP_MACRO_BUILTIN__LINE__}, }; for (usize i = 0; i < SCC_ARRLEN(builin_table); i += 1) { - scc_cstring_t builtin_name = - scc_cstring_from_cstr(builin_table[i].name); + scc_str_t builtin_name = scc_str_from_cstr(builin_table[i].name); scc_pproc_macro_t *builtin = scc_pproc_macro_new(&builtin_name, builin_table[i].type); scc_pproc_macro_table_set(macro_table, builtin); @@ -146,7 +145,7 @@ CONTINUE: } if (ret && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_INVALID) { - PanicFmt("Invalid token: %s", scc_cstring_as_cstr(&tok->lexeme)); + PanicFmt("Invalid token: %s", scc_str_as_cstr(&tok->lexeme)); } if (ret && !pp->ring_need_comment && scc_get_tok_subtype(tok->type) == SCC_TOK_SUBTYPE_COMMENT) { @@ -180,7 +179,7 @@ void scc_pproc_drop(scc_pproc_t *pp) { scc_ring_free(pp->expanded_ring); scc_vec_foreach(pp->include_paths, i) { - scc_cstring_free(&scc_vec_at(pp->include_paths, i)); + scc_str_drop(&scc_vec_at(pp->include_paths, i)); } scc_vec_free(pp->include_paths); diff --git a/libs/pproc/tests/test_pproc_unit.c b/libs/pproc/tests/test_pproc_unit.c index 82fd6d9..1786584 100644 --- a/libs/pproc/tests/test_pproc_unit.c +++ b/libs/pproc/tests/test_pproc_unit.c @@ -3,7 +3,7 @@ #include #include -static cbool process_input(const char *input, scc_cstring_t *output) { +static cbool process_input(const char *input, scc_str_t *output) { int ret = 0; scc_sstream_t mem_stream; ret = scc_sstream_init_by_buffer(&mem_stream, input, strlen(input), false, @@ -17,14 +17,14 @@ static cbool process_input(const char *input, scc_cstring_t *output) { scc_pproc_init(&pp, scc_lexer_to_ring(&lexer, 8, true)); scc_lexer_tok_ring_t *tok_ring = scc_pproc_to_ring(&pp, 8, true, true); - *output = scc_cstring_from_cstr(""); + *output = scc_str_from_cstr(""); scc_lexer_tok_t tok; while (1) { scc_ring_next_consume(*tok_ring, tok, ret); if (!ret) { break; } - scc_cstring_append(output, &tok.lexeme); + scc_str_append(output, &tok.lexeme); scc_lexer_tok_drop(&tok); } @@ -37,24 +37,24 @@ static cbool process_input(const char *input, scc_cstring_t *output) { #define CHECK_PP_OUTPUT_EXACT(input, expect) \ do { \ - scc_cstring_t output; \ + scc_str_t output; \ process_input(input, &output); \ assert(output.data != NULL); \ TEST_CHECK(strcmp(output.data, expect) == 0); \ TEST_MSG("Expected: %s", expect); \ TEST_MSG("Produced: %s", output.data); \ - scc_cstring_free(&output); \ + scc_str_drop(&output); \ } while (0) #define CHECK_PP_OUTPUT_CONTAIN(input, expect) \ do { \ - scc_cstring_t output; \ + scc_str_t output; \ process_input(input, &output); \ assert(output.data != NULL); \ TEST_CHECK(strstr(output.data, expect) != NULL); \ TEST_MSG("Expected: %s", expect); \ TEST_MSG("Produced: %s", output.data); \ - scc_cstring_free(&output); \ + scc_str_drop(&output); \ } while (0) static void test_define_simple_no_macro(void) { diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index 755bbf6..a74faec 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -16,11 +16,11 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path, name @number ... */ - scc_cstring_t fpath = scc_cstring_from_cstr(file_path); - scc_cstring_append_ch(&fpath, '/'); - scc_cstring_append_cstr(&fpath, dll_name, scc_strlen(dll_name)); - scc_cstring_append_cstr(&fpath, ".def", 4); - const char *fname = scc_cstring_as_cstr(&fpath); + scc_str_t fpath = scc_str_from_cstr(file_path); + scc_str_append_ch(&fpath, '/'); + scc_str_append_cstr(&fpath, dll_name, scc_strlen(dll_name)); + scc_str_append_cstr(&fpath, ".def", 4); + const char *fname = scc_str_as_cstr(&fpath); scc_file_t fp = scc_fopen(fname, SCC_FILE_READ); if (fp == null) { LOG_ERROR("load_from_def file read error: %s", fname); diff --git a/libs/tree_dump/include/scc_tree_dump.h b/libs/tree_dump/include/scc_tree_dump.h new file mode 100644 index 0000000..b795b09 --- /dev/null +++ b/libs/tree_dump/include/scc_tree_dump.h @@ -0,0 +1,99 @@ +#ifndef SCC_TREE_DUMP_H +#define SCC_TREE_DUMP_H + +#include "scc_core_str.h" +#include "scc_core_vec.h" + +typedef struct scc_tree_dump { + scc_str_t buf; // 字符串缓冲区 + SCC_VEC(cbool) stack; // 缩进栈:每个元素表示该层是否为最后一个子节点 + cbool use_color; // 是否启用颜色 + cbool line_start; // 当前是否在行首(需要输出缩进) + + // 可配置的缩进字符串 + const char *vertical; // "| " + const char *branch; // "|-" + const char *last_branch; // "`-" + const char *space; // " " + + // 颜色字符串(当 use_color 为 false 时为空字符串) + const char *node_color; // 节点名称颜色 + const char *value_color; // 值颜色 + const char *branch_color; // 分支符号颜色 + const char *reset_color; // 重置颜色 +} scc_tree_dump_t; + +/** + * @brief 初始化树形输出器 + * @param td 输出器指针 + * @param use_color 是否使用 ANSI 颜色 + */ +void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color); + +/** + * @brief 释放输出器占用的资源 + */ +void scc_tree_dump_drop(scc_tree_dump_t *td); + +/** + * @brief 清空当前缓冲区,但保留已分配内存 + */ +void scc_tree_dump_clear(scc_tree_dump_t *td); + +/** + * @brief 获取当前构建的字符串(以 '\0' 结尾) + * @return 内部缓冲区指针,不可 free + */ +const char *scc_tree_dump_cstr(scc_tree_dump_t *td); + +/** + * @brief 将缓冲区内容通过回调输出,并清空缓冲区 + * @param output 输出回调函数,接收字符串指针、长度、用户数据 + * @param user 用户数据 + */ +void scc_tree_dump_flush(scc_tree_dump_t *td, + void (*output)(const char *str, usize len, void *user), + void *user); + +/** + * @brief 开始一个新行(自动输出缩进) + * @note 通常不需要手动调用,因为 append 系列函数会自动处理 + */ +void scc_tree_dump_begin_line(scc_tree_dump_t *td); + +/** + * @brief 追加普通字符串(自动处理行首缩进) + */ +void scc_tree_dump_append(scc_tree_dump_t *td, const char *s); + +/** + * @brief 格式化追加(printf 风格) + */ +void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...); + +/** + * @brief 追加带节点颜色的文本 + */ +#define scc_tree_dump_node(td, fmt, ...) \ + scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->node_color, \ + ##__VA_ARGS__, (td)->reset_color) + +/** + * @brief 追加带值颜色的格式化文本 + */ +#define scc_tree_dump_value(td, fmt, ...) \ + scc_tree_dump_append_fmt(td, "%s" fmt "%s", (td)->value_color, \ + ##__VA_ARGS__, (td)->reset_color) + +/** + * @brief 推入新层级 + * @param is_last 该层级是否是父节点的最后一个子节点 + */ +void scc_tree_dump_push(scc_tree_dump_t *td, cbool is_last); + +/** + * @brief 弹出当前层级 + */ +void scc_tree_dump_pop(scc_tree_dump_t *td); + +#endif // SCC_TREE_DUMP_H diff --git a/libs/tree_dump/include/tree_dump.h b/libs/tree_dump/include/tree_dump.h deleted file mode 100644 index e0bd2e9..0000000 --- a/libs/tree_dump/include/tree_dump.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __SCC_TREE_DUMP_H__ -#define __SCC_TREE_DUMP_H__ - -#include - -#define SCC_TREE_DUMP_VERTICAL "| " -#define SCC_TREE_DUMP_BRANCH "|-" -#define SCC_TREE_DUMP_LAST_BRANCH "`-" -#define SCC_TREE_DUMP_SPACE " " - -#define SCC_TREE_DUMP_NODE_COLOR ANSI_FG_BLUE -#define SCC_TREE_DUMP_VALUE_COLOR ANSI_FG_GREEN -#define SCC_TREE_DUMP_BRANCH_COLOR ANSI_FG_YELLOW -#define SCC_TREE_DUMP_RESET_COLOR ANSI_NONE - -// #define ANSI_FMT - -typedef SCC_VEC(cbool) scc_ast_dump_stack_t; - -typedef void (*scc_tree_dump_output_t)(void *userdata, const char *fmt, ...); - -typedef struct { - scc_ast_dump_stack_t stack; ///< 每层是否为最后子节点 - cbool use_color; ///< 是否使用颜色输出 - - const char *vertical; - const char *branch; - const char *last_branch; - const char *space; - - const char *node_color; ///< 节点类型颜色 - const char *value_color; ///< 值颜色 - const char *branch_color; ///< 分支符号颜色 - const char *reset_color; ///< 重置颜色 - - scc_tree_dump_output_t output_func; - void *output_userdata; -} scc_tree_dump_ctx_t; - -static inline void scc_tree_dump_ctx_init(scc_tree_dump_ctx_t *ctx, - cbool use_color, - scc_tree_dump_output_t output_func, - void *output_userdata) { - ctx->use_color = use_color; - scc_vec_init(ctx->stack); - - ctx->vertical = SCC_TREE_DUMP_VERTICAL; - ctx->branch = SCC_TREE_DUMP_BRANCH; - ctx->last_branch = SCC_TREE_DUMP_LAST_BRANCH; - ctx->space = SCC_TREE_DUMP_SPACE; - - ctx->node_color = use_color ? SCC_TREE_DUMP_NODE_COLOR : ""; - ctx->value_color = use_color ? SCC_TREE_DUMP_VALUE_COLOR : ""; - ctx->branch_color = use_color ? SCC_TREE_DUMP_BRANCH_COLOR : ""; - ctx->reset_color = use_color ? SCC_TREE_DUMP_RESET_COLOR : ""; - - ctx->output_func = output_func; - ctx->output_userdata = output_userdata; -} - -#define scc_tree_dump_printf(ctx, fmt, ...) \ - (ctx)->output_func((ctx)->output_userdata, fmt, ##__VA_ARGS__) - -static inline void scc_tree_dump_ctx_drop(scc_tree_dump_ctx_t *ctx) { - scc_vec_free(ctx->stack); -} - -// 打印缩进 -static inline void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) { - scc_vec_foreach(ctx->stack, i) { - cbool last_child = scc_vec_at(ctx->stack, i); - const char *data = null; - if (i + 1 == scc_vec_size(ctx->stack)) { - // 最后一层打印分支符号 - data = last_child ? ctx->last_branch : ctx->branch; - } else { - data = last_child ? ctx->space : ctx->vertical; - } - Assert(data != null); - if (ctx->use_color) { - ctx->output_func(ctx->output_userdata, "%s%s%s", ctx->branch_color, - data, ctx->reset_color); - } else { - ctx->output_func(ctx->output_userdata, "%s", data); - } - } -} - -#define SCC_TREE_DUMP_PRINT_COLORED(ctx, color, before_str, fmt, after_str, \ - ...) \ - (ctx)->output_func((ctx)->output_userdata, \ - before_str "%s" fmt "%s" after_str, \ - (ctx)->use_color ? color : "", ##__VA_ARGS__, \ - (ctx)->use_color ? ANSI_NONE : ""); - -#define SCC_TREE_DUMP_PRINT_AROUND(ctx, color, around_str, fmt, ...) \ - SCC_TREE_DUMP_PRINT_COLORED(ctx, color, around_str, fmt, around_str, \ - ##__VA_ARGS__) - -#define SCC_TREE_DUMP_PRINT_PURE(ctx, color, fmt, ...) \ - SCC_TREE_DUMP_PRINT_COLORED(ctx, color, "", fmt, "", ##__VA_ARGS__) - -// 推入新的层级到栈中 -static inline void scc_tree_dump_push_level(scc_tree_dump_ctx_t *ctx, - cbool is_last_child) { - scc_vec_push(ctx->stack, is_last_child); -} - -// 弹出当前层级 -static inline void scc_tree_dump_pop_level(scc_tree_dump_ctx_t *ctx) { - (void)scc_vec_pop(ctx->stack); -} - -// 获取当前层级深度 -static inline usize scc_tree_dump_depth(scc_tree_dump_ctx_t *ctx) { - return scc_vec_size(ctx->stack); -} - -#endif /* __SCC_TREE_DUMP_H__ */ diff --git a/libs/tree_dump/src/scc_tree_dump.c b/libs/tree_dump/src/scc_tree_dump.c new file mode 100644 index 0000000..6864ecf --- /dev/null +++ b/libs/tree_dump/src/scc_tree_dump.c @@ -0,0 +1,126 @@ +#include + +#define DEFAULT_VERTICAL "| " +#define DEFAULT_BRANCH "|-" +#define DEFAULT_LAST_BRANCH "`-" +#define DEFAULT_SPACE " " +#define NODE_COLOR "\033[34m" +#define VALUE_COLOR "\033[32m" +#define BRANCH_COLOR "\033[33m" +#define RESET_COLOR "\033[0m" + +void scc_tree_dump_init(scc_tree_dump_t *td, cbool use_color) { + scc_str_init(&td->buf); + scc_vec_init(td->stack); + td->use_color = use_color; + td->line_start = true; + + td->vertical = DEFAULT_VERTICAL; + td->branch = DEFAULT_BRANCH; + td->last_branch = DEFAULT_LAST_BRANCH; + td->space = DEFAULT_SPACE; + + td->node_color = use_color ? NODE_COLOR : ""; + td->value_color = use_color ? VALUE_COLOR : ""; + td->branch_color = use_color ? BRANCH_COLOR : ""; + td->reset_color = use_color ? RESET_COLOR : ""; +} + +void scc_tree_dump_drop(scc_tree_dump_t *td) { + scc_str_drop(&td->buf); + scc_vec_free(td->stack); +} + +void scc_tree_dump_clear(scc_tree_dump_t *td) { + scc_str_clear(&td->buf); + td->line_start = true; +} + +const char *scc_tree_dump_cstr(scc_tree_dump_t *td) { + return scc_str_as_cstr(&td->buf); +} + +void scc_tree_dump_flush(scc_tree_dump_t *td, + void (*output)(const char *str, usize len, void *user), + void *user) { + if (td->buf.size > 1 && output) { + output(td->buf.data, td->buf.size - 1, user); + } + scc_tree_dump_clear(td); +} + +void scc_tree_dump_begin_line(scc_tree_dump_t *td) { + if (!td->line_start) { + // 如果不在行首,先换行(表示上一行结束) + if (td->buf.size > 1) { + scc_str_append_ch(&td->buf, '\n'); + } + } + // 输出缩进 + usize depth = scc_vec_size(td->stack); + for (usize i = 0; i < depth; i++) { + cbool last = scc_vec_at(td->stack, i); + const char *prefix; + if (i + 1 == depth) { + prefix = last ? td->last_branch : td->branch; + } else { + prefix = last ? td->space : td->vertical; + } + if (td->use_color) { + scc_str_append_fmt(&td->buf, "%s%s%s", td->branch_color, prefix, + td->reset_color); + } else { + scc_str_append_cstr(&td->buf, prefix, scc_strlen(prefix)); + } + } + td->line_start = false; +} + +void scc_tree_dump_append(scc_tree_dump_t *td, const char *s) { + if (td->line_start) { + scc_tree_dump_begin_line(td); + } + scc_str_append_cstr(&td->buf, s, scc_strlen(s)); +} + +void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...) { + if (td->line_start) { + scc_tree_dump_begin_line(td); + } + va_list args; + va_start(args, fmt); + // 计算所需长度 + va_list args_copy; + va_copy(args_copy, args); + usize len = scc_vsnprintf(null, 0, fmt, args_copy); + va_end(args_copy); + if (len == 0) { + va_end(args); + return; + } + // 确保缓冲区容量足够 + if (td->buf.size + len + 1 > td->buf.cap) { + usize new_cap = td->buf.cap; + while (new_cap < td->buf.size + len + 1) { + new_cap = new_cap ? new_cap * 2 : 16; + } + char *new_data = (char *)scc_realloc(td->buf.data, new_cap); + Assert(new_data != null); + td->buf.data = new_data; + td->buf.cap = new_cap; + } + scc_vsnprintf(td->buf.data + td->buf.size - (td->buf.size == 0 ? 0 : 1), + len + 1, fmt, args); + va_end(args); + if (td->buf.size == 0) { + td->buf.size = 1; + } + td->buf.size += len; + td->buf.data[td->buf.size - 1] = '\0'; +} + +void scc_tree_dump_push(scc_tree_dump_t *td, cbool is_last) { + scc_vec_push(td->stack, is_last); +} + +void scc_tree_dump_pop(scc_tree_dump_t *td) { (void)scc_vec_pop(td->stack); } diff --git a/runtime/scc_core/include/scc_core_str.h b/runtime/scc_core/include/scc_core_str.h index 50b923c..4e297f3 100644 --- a/runtime/scc_core/include/scc_core_str.h +++ b/runtime/scc_core/include/scc_core_str.h @@ -10,22 +10,22 @@ * @brief 动态字符串结构体 * @attention 创建的字符串对象需要使用 scc_cstring_free 释放 */ -typedef struct scc_cstring { +typedef struct scc_str { usize size; /**< 字符串当前大小(包括结尾的'\0')*/ usize cap; /**< 分配的容量 */ char *data; /**< 实际存储数据的指针 */ -} scc_cstring_t; +} scc_str_t; /** * @brief 创建一个新的空动态字符串对象 * * @return cstring_t 初始化后的对象 */ -static inline scc_cstring_t scc_cstring_create(void) { - return (scc_cstring_t){.data = null, .size = 0, .cap = 0}; +static inline scc_str_t scc_str_empty(void) { + return (scc_str_t){.data = null, .size = 0, .cap = 0}; } -static inline void scc_cstring_init(scc_cstring_t *string) { +static inline void scc_str_init(scc_str_t *string) { Assert(string != null); string->data = null; string->size = 0; @@ -38,9 +38,9 @@ static inline void scc_cstring_init(scc_cstring_t *string) { * @param s 输入的 C 风格字符串 * @return cstring_t 新建对象,包含输入字符串的副本 */ -static inline scc_cstring_t scc_cstring_from_cstr(const char *s) { +static inline scc_str_t scc_str_from_cstr(const char *s) { if (s == null) { - return scc_cstring_create(); + return scc_str_empty(); } usize len = 0; @@ -53,11 +53,11 @@ static inline scc_cstring_t scc_cstring_from_cstr(const char *s) { scc_memcpy(data, s, len); data[len] = '\0'; - return (scc_cstring_t){.size = len + 1, .cap = len + 1, .data = data}; + return (scc_str_t){.size = len + 1, .cap = len + 1, .data = data}; } -static inline scc_cstring_t scc_cstring_copy(const scc_cstring_t *s) { - return scc_cstring_from_cstr(s->data); +static inline scc_str_t scc_str_copy(const scc_str_t *s) { + return scc_str_from_cstr(s->data); } /** @@ -65,7 +65,7 @@ static inline scc_cstring_t scc_cstring_copy(const scc_cstring_t *s) { * * @param str 要被释放的字符串指针 */ -static inline void scc_cstring_free(scc_cstring_t *str) { +static inline void scc_str_drop(scc_str_t *str) { if (str == null) { return; } @@ -84,8 +84,8 @@ static inline void scc_cstring_free(scc_cstring_t *str) { * @param data 要追加的 C 字符串指针 * @param len 要追加的 C 字符串长度 */ -static inline void scc_cstring_append_cstr(scc_cstring_t *str, const char *data, - usize len) { +static inline void scc_str_append_cstr(scc_str_t *str, const char *data, + usize len) { if (str == null || data == null || len == 0) { return; } @@ -127,19 +127,48 @@ static inline void scc_cstring_append_cstr(scc_cstring_t *str, const char *data, * @param str 目标动态字符串指针 * @param other 要追加的动态字符串指针 */ -static inline void scc_cstring_append(scc_cstring_t *str, - const scc_cstring_t *other) { - scc_cstring_append_cstr(str, other->data, other->size - 1); +static inline void scc_str_append(scc_str_t *str, const scc_str_t *other) { + scc_str_append_cstr(str, other->data, other->size - 1); } +#ifndef __SCC_PURE_LIB__ +#include "scc_core_impl.h" +static inline void scc_str_append_fmt(scc_str_t *str, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + usize needed = scc_vsnprintf(null, 0, fmt, args); + va_end(args); + if (needed == 0) + return; + + // 确保容量足够(需要额外空间给 '\0') + if (str->size + needed + 1 > str->cap) { + usize new_cap = str->cap; + while (new_cap < str->size + needed + 1) { + new_cap = new_cap ? new_cap * 2 : (needed + 16); + } + char *new_data = (char *)scc_realloc(str->data, new_cap); + Assert(new_data != NULL); + str->data = new_data; + str->cap = new_cap; + } + + va_start(args, fmt); + scc_vsnprintf(str->data + str->size - 1, needed + 1, fmt, args); + va_end(args); + str->size += needed; + // 确保结尾 '\0'(scc_vsnprintf 已添加) +} +#endif + /** * @brief 向动态字符串末尾追加一个字符 * * @param str 目标动态字符串指针 * @param ch 要追加的字符 */ -static inline void scc_cstring_append_ch(scc_cstring_t *str, char ch) { - scc_cstring_append_cstr(str, &ch, 1); +static inline void scc_str_append_ch(scc_str_t *str, char ch) { + scc_str_append_cstr(str, &ch, 1); } /** @@ -148,7 +177,7 @@ static inline void scc_cstring_append_ch(scc_cstring_t *str, char ch) { * @param str 动态字符串指针 * @return usize 字符串实际长度 */ -static inline usize scc_cstring_len(const scc_cstring_t *str) { +static inline usize scc_str_len(const scc_str_t *str) { if (str == null) { return 0; } @@ -164,7 +193,7 @@ static inline usize scc_cstring_len(const scc_cstring_t *str) { * @param str 动态字符串指针 * @return cbool */ -static inline cbool scc_cstring_is_empty(const scc_cstring_t *str) { +static inline cbool scc_str_is_empty(const scc_str_t *str) { return str == null || str->size == 0; } @@ -173,7 +202,7 @@ static inline cbool scc_cstring_is_empty(const scc_cstring_t *str) { * * @param str 动态字符串指针 */ -static inline void scc_cstring_clear(scc_cstring_t *str) { +static inline void scc_str_clear(scc_str_t *str) { if (str) { str->size = 1; if (str->data) { @@ -188,19 +217,18 @@ static inline void scc_cstring_clear(scc_cstring_t *str) { * @param str 动态字符串指针 * @return char* 返回指向内部缓冲区的 C 风格字符串指针 */ -static inline char *scc_cstring_as_cstr(const scc_cstring_t *str) { +static inline char *scc_str_as_cstr(const scc_str_t *str) { if (str == null || str->data == null) { return null; } return str->data; } -static inline int scc_cstring_cmp(const scc_cstring_t *str1, - const scc_cstring_t *str2) { - return scc_strcmp(scc_cstring_as_cstr(str1), scc_cstring_as_cstr(str2)); +static inline int scc_str_equal(const scc_str_t *str1, const scc_str_t *str2) { + return scc_strcmp(scc_str_as_cstr(str1), scc_str_as_cstr(str2)); } -static inline char *scc_cstring_move_cstr(scc_cstring_t *str) { +static inline char *scc_str_move_cstr(scc_str_t *str) { if (str == null || str->data == null) { return null; } @@ -211,8 +239,8 @@ static inline char *scc_cstring_move_cstr(scc_cstring_t *str) { return ret; } -static inline scc_cstring_t scc_cstring_move(scc_cstring_t *str) { - return scc_cstring_from_cstr(scc_cstring_move_cstr(str)); +static inline scc_str_t scc_str_move(scc_str_t *str) { + return scc_str_from_cstr(scc_str_move_cstr(str)); } #endif /* __SCC_CORE_STR_H__ */ diff --git a/src/main.c b/src/main.c index b349e05..2c0b4fa 100644 --- a/src/main.c +++ b/src/main.c @@ -24,7 +24,7 @@ static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) { } else if (verbose >= 1) { scc_printf( "token [%-8s] `%s` at %s:%d:%d\n", scc_get_tok_name(tok.type), - tok.type != SCC_TOK_ENDLINE ? scc_cstring_as_cstr(&tok.lexeme) + tok.type != SCC_TOK_ENDLINE ? scc_str_as_cstr(&tok.lexeme) : "\\n", tok.loc.name, tok.loc.line, tok.loc.col); } @@ -42,11 +42,11 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) { break; } if (fp == scc_stdout) { - scc_printf("%s", scc_cstring_as_cstr(&tok.lexeme)); + scc_printf("%s", scc_str_as_cstr(&tok.lexeme)); } else { - usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme), - scc_cstring_len(&tok.lexeme)); - if (ret != scc_cstring_len(&tok.lexeme)) { + usize ret = scc_fwrite(fp, scc_str_as_cstr(&tok.lexeme), + scc_str_len(&tok.lexeme)); + if (ret != scc_str_len(&tok.lexeme)) { LOG_FATAL("Failed to write to file"); } } @@ -55,6 +55,10 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) { scc_fclose(fp); } +static void tree_dump_output(const char *str, usize len, void *user) { + scc_fprintf(user, "%.*s", (int)len, str); +} + void init_platform(void); int main(int argc, const char **argv, const char **envp) { @@ -139,7 +143,7 @@ int main(int argc, const char **argv, const char **envp) { scc_lexer_tok_vec_t pproc_tok_vec; scc_vec_init(pproc_tok_vec); scc_lexer_tok_t tok = { - .lexeme = scc_cstring_from_cstr("1"), + .lexeme = scc_str_from_cstr("1"), .type = SCC_TOK_INT_LITERAL, .loc.name = "", .loc.line = 0, @@ -147,10 +151,10 @@ int main(int argc, const char **argv, const char **envp) { .loc.offset = 0, }; scc_vec_push(pproc_tok_vec, tok); - scc_cstring_t pproc_predefined_macros[] = { - scc_cstring_from_cstr("__SCC__"), - scc_cstring_from_cstr("_WIN64"), - scc_cstring_from_cstr("__x86_64__"), + scc_str_t pproc_predefined_macros[] = { + scc_str_from_cstr("__SCC__"), + scc_str_from_cstr("_WIN64"), + scc_str_from_cstr("__x86_64__"), }; for (usize i = 0; i < SCC_ARRLEN(pproc_predefined_macros); i += 1) { scc_vec_init(pproc_tok_vec); @@ -193,16 +197,16 @@ sstream_drop: } if (config.emit_ast) { - scc_tree_dump_ctx_t tree_dump; + scc_tree_dump_t tree_dump; if (fp == null) { - scc_tree_dump_ctx_init(&tree_dump, true, (void *)scc_fprintf, - (void *)scc_stdout); + scc_tree_dump_init(&tree_dump, true); } else { - scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf, - (void *)fp); + scc_tree_dump_init(&tree_dump, false); } scc_ast_dump_node(&tree_dump, (scc_ast_node_t *)translation_unit); - scc_tree_dump_ctx_drop(&tree_dump); + scc_tree_dump_flush(&tree_dump, tree_dump_output, + fp == null ? scc_stdout : fp); + scc_tree_dump_drop(&tree_dump); return 0; } @@ -216,18 +220,19 @@ sstream_drop: if (config.emit_ir) { scc_ir_dump_ctx_t ir_dump_ctx; - scc_tree_dump_ctx_t tree_dump; + scc_tree_dump_t tree_dump; if (fp == null) { - scc_tree_dump_ctx_init(&tree_dump, true, (void *)scc_fprintf, - (void *)scc_stdout); + scc_tree_dump_init(&tree_dump, true); } else { - scc_tree_dump_ctx_init(&tree_dump, false, (void *)scc_fprintf, - (void *)fp); + scc_tree_dump_init(&tree_dump, false); } scc_ir_dump_ctx_init(&ir_dump_ctx, &tree_dump, &cprog); // scc_ir_dump_cprog(&ir_dump_ctx); scc_ir_dump_cprog_linear(&ir_dump_ctx); - scc_tree_dump_ctx_drop(&tree_dump); + + scc_tree_dump_flush(&tree_dump, tree_dump_output, + fp == null ? scc_stdout : fp); + scc_tree_dump_drop(&tree_dump); return 0; } diff --git a/tests/simple/12_include.c b/tests/simple/12_include.c deleted file mode 100644 index 518e70d..0000000 --- a/tests/simple/12_include.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "scc_stdio.h" - -int main(void) { - puts("hello world"); - const char *str = "hello world"; - puts(str); - return 0; -} diff --git a/tests/simple/12_logic.c b/tests/simple/12_logic.c new file mode 100644 index 0000000..2d6df72 --- /dev/null +++ b/tests/simple/12_logic.c @@ -0,0 +1,9 @@ +int check(int i) { return i >= 0 && i < 10; } + +int main() { + int num = 0; + for (int i = 0; check(i); i += 1) { + num = num + 1; + } + return num; +} diff --git a/tests/simple/13_array.c b/tests/simple/13_array.c new file mode 100644 index 0000000..4d007b8 --- /dev/null +++ b/tests/simple/13_array.c @@ -0,0 +1,8 @@ +int main(void) { + char buff[] = "hello buffer"; + int res = 0; + for (char *ptr = buff; *ptr != 0; ptr += 1) { + res += *ptr; + } + return res; +} diff --git a/tests/simple/expect.toml b/tests/simple/expect.toml index c7e6083..e225f7e 100644 --- a/tests/simple/expect.toml +++ b/tests/simple/expect.toml @@ -1,4 +1,5 @@ [return_val_cases] +# windows: echo $LASTEXITCODE "./01_return.c" = 65536 "./02_decl_expr.c" = 1 "./03_decl_init.c" = 11 @@ -10,4 +11,6 @@ "./09_for.c" = 10 "./10_main.c" = 3 "./11_recursive.c" = 120 +"./12_logic.c" = 10 +"./13_array.c" = 1198 [stdout_val_cases] diff --git a/tests/simple/scc_stdio.h b/tests/simple/scc_stdio.h index e709413..00dd77d 100644 --- a/tests/simple/scc_stdio.h +++ b/tests/simple/scc_stdio.h @@ -2,5 +2,6 @@ #define __SCC_STDIO_H__ extern int puts(const char *str); +extern char *gets(char *buff); #endif