feat(ast): 更新AST dump功能以使用新的树转储接口

- 将头文件中的tree_dump.h替换为scc_tree_dump.h
- 修改函数签名将scc_tree_dump_ctx_t改为scc_tree_dump_t
- 移除过时的宏定义和内联函数实现
- 使用新的scc_tree_dump_* API替代旧的PRINT_*宏
- 简化类型、表达式、语句和声明的转储逻辑
- 统一使用新的树转储接口进行节点和值的输出

feat(ast2ir): 实现逻辑运算符和一元运算符的IR转换

- 添加scc_ast2ir_logical_expr函数处理&&和||运算符
- 实现短路求值逻辑,包含分支控制流
- 添加对一元正号运算符的支持
- 实现取地址和间接寻址运算符
- 添加字符字面量解析支持转义序列

fix(ir): 修复字符串常量构建中的长度计算错误

- 修正数组长度计算从len+1改为len-1
- 调整字符串内容复制逻辑跳过引号边界
- 修正内存分配大小与实际数据长度匹配

refactor(ir): 更新IR转储模块使用统一的树转储接口

- 将IR转储上下文中的tree_dump_ctx_t替换为scc_tree_dump_t
- 更新初始化函数签名以使用新的转储接口类型
This commit is contained in:
zzy
2026-04-03 20:10:51 +08:00
parent 78e7c800ba
commit ca187c78f1
42 changed files with 1264 additions and 1212 deletions

View File

@@ -7,7 +7,7 @@
#define __SCC_AST_DUMP_H__
#include "ast_def.h"
#include <tree_dump.h>
#include <scc_tree_dump.h>
/**
* @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__ */

View File

@@ -4,15 +4,7 @@
*/
#include <ast_dump.h>
#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 <scc_tree_dump.h>
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, "<anonymous struct>");
}
if (type->record.name)
scc_tree_dump_value(td, " 'struct %s'", type->record.name);
else
scc_tree_dump_value(td, " <anonymous struct>");
break;
case SCC_AST_TYPE_UNION:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "<anonymous union>");
}
if (type->record.name)
scc_tree_dump_value(td, " 'union %s'", type->record.name);
else
scc_tree_dump_value(td, " <anonymous union>");
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);
}

View File

@@ -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,

View File

@@ -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 设置当前基本块
*/

View File

@@ -2,15 +2,14 @@
#define __SCC_IR_DUMP_H__
#include "ir_prog.h"
#include <tree_dump.h>
#include <scc_tree_dump.h>
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);

View File

@@ -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__ */

View File

@@ -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;

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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 {

View File

@@ -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(

View File

@@ -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 =

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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)

View File

@@ -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);

View File

@@ -4,7 +4,7 @@
#include <utest/acutest.h>
// 辅助函数:释放 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); \

View File

@@ -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;

View File

@@ -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:

View File

@@ -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.");

View File

@@ -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) {

View File

@@ -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 = "<anonymous struct>";
}
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 = "<anonymous union>";
}
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 = "<anonymous enum>";
}
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) {

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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, &macro->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);

View File

@@ -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 {

View File

@@ -2,9 +2,9 @@
#include <scc_core_ring.h>
#include <scc_pproc.h>
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 <FILENAME>");
scc_cstring_free(&line);
scc_str_drop(&line);
}

View File

@@ -1,7 +1,7 @@
#include <pproc_macro.h>
// 创建宏对象
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(&macro->name);
scc_str_drop(&macro->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(&macros->table, &macro->name);
if (existing) {
LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(&macro->name));
LOG_WARN("Redefining macro: %s", scc_str_as_cstr(&macro->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(&macros->table, &macro->name);
if (existing) {
LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(&macro->name));
LOG_WARN("Redefining macro: %s", scc_str_as_cstr(&macro->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(&macro->name) != 0);
Assert(pp != null && macro != null && scc_str_len(&macro->name) != 0);
scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, &macro->name, macro);
if (old && old != macro) {
LOG_WARN("same macro name `%s`", scc_cstring_as_cstr(&macro->name));
LOG_WARN("same macro name `%s`", scc_str_as_cstr(&macro->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) {

View File

@@ -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);

View File

@@ -3,7 +3,7 @@
#include <string.h>
#include <utest/acutest.h>
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) {

View File

@@ -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);

View File

@@ -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

View File

@@ -1,119 +0,0 @@
#ifndef __SCC_TREE_DUMP_H__
#define __SCC_TREE_DUMP_H__
#include <scc_core.h>
#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__ */

View File

@@ -0,0 +1,126 @@
#include <scc_tree_dump.h>
#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); }

View File

@@ -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__ */

View File

@@ -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 = "<internal>",
.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;
}

View File

@@ -1,8 +0,0 @@
#include "scc_stdio.h"
int main(void) {
puts("hello world");
const char *str = "hello world";
puts(str);
return 0;
}

9
tests/simple/12_logic.c Normal file
View File

@@ -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;
}

8
tests/simple/13_array.c Normal file
View File

@@ -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;
}

View File

@@ -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]

View File

@@ -2,5 +2,6 @@
#define __SCC_STDIO_H__
extern int puts(const char *str);
extern char *gets(char *buff);
#endif