Compare commits

...

3 Commits

Author SHA1 Message Date
zzy
27d86d5685 feat(ast2ir): 添加指针运算支持并修复整数字面量解析
- 实现了指针解引用(*)和取地址(&)操作符的IR转换
- 添加parse_lexme2const_int函数统一处理整数字面量解析
- 支持数组大小表达式的常量解析
- 修复函数缺少返回语句的问题,在函数末尾添加默认ret指令

refactor(ir_builder): 调整函数参数类型处理逻辑

- 修改函数参数以指针形式传递,更新参数类型处理方式
- 优化参数节点创建过程,将参数类型包装为指针类型

fix(ir_dump): 修正IR输出格式问题

- 调整基本块和函数的输出格式,确保正确的换行和缩进
- 统一输出格式,提升可读性

feat(ir2mcode): 添加帧管理器头文件定义

- 定义frame_manager.h接口,包含栈帧分配相关函数声明
- 提供栈槽分配、寄存器保存、偏移计算等功能接口

refactor(reg_alloc): 添加初始栈大小配置

- 在寄存器分配器中增加init_stack_size字段
- 支持初始化栈大小设置,为后续帧管理功能做准备

test: 添加指针操作测试用例

- 新增14_pointer.c测试文件,验证指针取地址和解引用功能
- 在expect.toml中添加对应的期望返回值
2026-04-04 13:22:19 +08:00
zzy
ca187c78f1 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
- 更新初始化函数签名以使用新的转储接口类型
2026-04-03 20:10:51 +08:00
zzy
78e7c800ba refactor(ir): 将IR节点重构为值引用并添加字符串字面量支持
- 将scc_ir_node_ref_t重命名为scc_ir_value_ref_t,并更新所有相关API
- 修改IR定义中的节点标签枚举为值标签枚举(scc_ir_node_tag_t -> scc_ir_value_tag_t)
- 更新AST到IR转换器中所有节点引用的类型声明
- 添加对内置类型(VOID, CHAR, INT等)的完整映射实现
- 实现字符串字面量的常量数组创建功能
- 更新项目名称从"Simple Modual C Compiler"为"Simple C Compiler"
- 在Doxyfile中排除external目录的文档生成
- 移除未使用的strpool字段并重命名decl到IR的映射表

BREAKING CHANGE: IR节点引用类型已更改,所有使用scc_ir_node_ref_t的地方需
替换为scc_ir_value_ref_t。
2026-03-31 11:42:14 +08:00
57 changed files with 2258 additions and 1873 deletions

View File

@@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = "Simple Modual C Compiler"
PROJECT_NAME = "Simple C Compiler"
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@@ -1112,7 +1112,7 @@ EXCLUDE_SYMLINKS = NO
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
EXCLUDE_PATTERNS = */external/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the

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

@@ -8,9 +8,9 @@
typedef struct {
scc_ir_builder_t builder;
scc_hashtable_t node2ir; ///< decl to ir_ref
scc_hashtable_t decl2ir_ref; ///< decl to ir_ref
scc_hashtable_t symtab; ///< symbol to ir_ref
scc_strpool_t strpool; ///< string pool
// scc_strpool_t strpool; ///< string pool
const scc_type_abi_t *abi;
} scc_ast2ir_ctx_t;
@@ -21,8 +21,8 @@ void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
scc_ast_translation_unit_t *tu);
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl);
scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue);
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue);
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt);
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
scc_ast_type_t *ast_type);

View File

@@ -1,5 +1,15 @@
#include <scc_ast2ir.h>
static inline void parse_lexme2const_int(const char *lexme,
scc_ir_const_int_t *value) {
// FIXME
usize int_lit = 0;
for (usize i = 0; i < scc_strlen(lexme); i++) {
int_lit = int_lit * 10 + (lexme[i] - '0');
}
value->int64 = int_lit;
}
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
scc_ast_type_t *ast_type) {
if (ctx == null || ast_type == null) {
@@ -13,6 +23,23 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
// 映射内置类型
scc_ir_type_init(&ir_type, SCC_IR_TYPE_i32);
// TODO: 根据具体内置类型设置
switch (ast_type->builtin.type) {
case SCC_AST_BUILTIN_TYPE_VOID:
return scc_ir_builder_type_void(&ctx->builder);
case SCC_AST_BUILTIN_TYPE_CHAR:
case SCC_AST_BUILTIN_TYPE_UNSIGNED_CHAR:
return scc_ir_builder_type_u8(&ctx->builder);
case SCC_AST_BUILTIN_TYPE_SIGNED_CHAR:
return scc_ir_builder_type_i8(&ctx->builder);
case SCC_AST_BUILTIN_TYPE_INT:
case SCC_AST_BUILTIN_TYPE_SIGNED_INT:
return scc_ir_builder_type_i32(&ctx->builder);
case SCC_AST_BUILTIN_TYPE_UNSIGNED_INT:
return scc_ir_builder_type_u32(&ctx->builder);
default:
Panic("Unsupported AST type: %d", ast_type->builtin.type);
break;
}
break;
}
@@ -34,7 +61,16 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
ir_type.data.array.base = element_type;
// TODO: 处理数组大小表达式
ir_type.data.array.len = 0; // 暂时设为0
ir_type.data.array.len = 0;
if (ast_type->array.size) {
// TODO constant expression
if (ast_type->array.size->base.type != SCC_AST_EXPR_INT_LITERAL) {
Panic("TODO: array size expression");
}
scc_ir_const_int_t value;
parse_lexme2const_int(ast_type->array.size->literal.lexme, &value);
ir_type.data.array.len = value.int32;
}
break;
}
@@ -76,15 +112,101 @@ 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
*
* @param ctx
* @param expr
* @return scc_ir_node_ref_t
* @return scc_ir_value_ref_t
*/
scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue) {
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue) {
if (ctx == null || expr == null) {
LOG_ERROR("args is null");
return 0;
@@ -94,7 +216,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
switch (expr->base.type) {
case SCC_AST_EXPR_BINARY: {
scc_ast_expr_t tmp_expr;
scc_ir_node_ref_t lhs, rhs;
scc_ir_value_ref_t lhs, rhs;
switch (expr->binary.op) {
case SCC_AST_OP_ASSIGN: // =
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
@@ -201,7 +323,7 @@ scc_ir_node_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);
@@ -212,7 +334,21 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
}
case SCC_AST_EXPR_UNARY: {
scc_ir_node_ref_t operand =
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
return scc_ast2ir_expr(ctx, expr->unary.operand, true);
} else if (expr->unary.op == SCC_AST_OP_INDIRECTION) {
// 从地址取值
scc_ir_value_ref_t ptr =
scc_ast2ir_expr(ctx, expr->unary.operand, false);
if (is_lvalue) {
// 作为左值使用(如 *ptr = ...),直接返回指针值(地址)
return ptr;
} else {
// 作为右值使用(如 x = *ptr加载指针指向的值
return scc_ir_builder_load(&ctx->builder, ptr);
}
}
scc_ir_value_ref_t operand =
scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue);
// /* 一元操作符 */
// SCC_AST_OP_UNARY_PLUS, // + (一元)
@@ -226,17 +362,24 @@ scc_ir_node_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
scc_ir_const_int_t value;
scc_ir_type_ref_t type_ref = scc_ir_builder_type_i32(&ctx->builder);
value.int32 = 0;
scc_ir_node_ref_t zero_ref =
scc_ir_value_ref_t zero_ref =
scc_ir_builder_const_int(&ctx->builder, type_ref, value);
return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_SUB, zero_ref,
operand);
}
case SCC_AST_OP_ADDRESS_OF:
case SCC_AST_OP_INDIRECTION:
UNREACHABLE();
break;
case SCC_AST_OP_BITWISE_NOT:
// 按位取反
return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_NOT, operand,
@@ -247,7 +390,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
scc_ir_const_int_t value;
scc_ir_type_ref_t type_ref = scc_ir_builder_type_i32(&ctx->builder);
value.int32 = 0;
scc_ir_node_ref_t zero_ref =
scc_ir_value_ref_t zero_ref =
scc_ir_builder_const_int(&ctx->builder, type_ref, value);
return scc_ir_builder_binop(&ctx->builder, SCC_IR_OP_EQ, zero_ref,
operand);
@@ -270,19 +413,19 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
scc_vec_foreach(expr->call.args, i) {
scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i);
scc_ir_node_ref_t arg_node;
scc_ir_value_ref_t arg_node;
arg_node = scc_ast2ir_expr(ctx, arg_expr, false);
scc_vec_push(args, arg_node);
}
// 创建调用节点(需要查找函数定义)
scc_ir_func_ref_t func = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
scc_ir_func_ref_t func = (scc_ir_value_ref_t)(usize)scc_hashtable_get(
&ctx->symtab, expr->call.callee->identifier._target->name);
if (!func) {
LOG_ERROR("Function %s not found",
expr->call.callee->identifier._target->name);
}
scc_ir_node_ref_t node =
scc_ir_value_ref_t node =
scc_ir_builder_call(&ctx->builder, func, args.data, args.size);
scc_vec_free(args);
return node;
@@ -300,30 +443,58 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
case SCC_AST_EXPR_INT_LITERAL: {
// FIXME maybe using some array to int;
usize int_lit = 0;
for (usize i = 0; i < scc_strlen(expr->literal.lexme); i++) {
int_lit = int_lit * 10 + (expr->literal.lexme[i] - '0');
}
scc_ir_type_ref_t type_ref = scc_ir_builder_type_i32(&ctx->builder);
scc_ir_const_int_t value;
parse_lexme2const_int(expr->literal.lexme, &value);
return scc_ir_builder_const_int(&ctx->builder, type_ref, value);
}
// SCC_AST_EXPR_FLOAT_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);
}
// SCC_AST_EXPR_INT_LITERAL, // 整数字面量
// SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
// SCC_AST_EXPR_CHAR_LITERAL, // 字符字面量
// case SCC_AST_EXPR_STRING_LITERAL: {
// return scc_ir_builder_store();
// }
case SCC_AST_EXPR_STRING_LITERAL: {
// FIXME
scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme,
scc_strlen(expr->literal.lexme));
if (is_lvalue)
TODO();
break;
}
case SCC_AST_EXPR_IDENTIFIER: {
if (expr->identifier._target == null) {
LOG_ERROR("unknown identifier %s", expr->identifier.name);
}
// FIXME hack hashtable
scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
&ctx->node2ir, expr->identifier._target);
scc_ir_value_ref_t in = (scc_ir_value_ref_t)(usize)scc_hashtable_get(
&ctx->decl2ir_ref, expr->identifier._target);
Assert(in != 0);
if (is_lvalue) {
return in;
@@ -389,7 +560,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_bblock_ref_t merge_block =
scc_ir_builder_bblock(&ctx->builder, "if_merge");
scc_ir_node_ref_t cond_node =
scc_ir_value_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->if_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, true_block,
false_block);
@@ -421,7 +592,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_builder_jump(&ctx->builder, cond_block);
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
scc_ir_node_ref_t cond_node =
scc_ir_value_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block);
@@ -448,7 +619,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_builder_jump(&ctx->builder, cond_block);
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
scc_ir_node_ref_t cond_node =
scc_ir_value_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block);
@@ -481,7 +652,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
if (stmt->for_stmt.cond) {
scc_ir_node_ref_t cond_node =
scc_ir_value_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->for_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, body_block,
exit_block);
@@ -507,7 +678,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
// SCC_AST_STMT_CONTINUE, // continue 语句
case SCC_AST_STMT_RETURN: {
if (stmt->return_stmt.expr) {
scc_ir_node_ref_t ret_val_node =
scc_ir_value_ref_t ret_val_node =
scc_ast2ir_expr(ctx, stmt->return_stmt.expr, false);
scc_ir_builder_ret(&ctx->builder, ret_val_node);
} else {
@@ -541,16 +712,17 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
scc_ir_type_ref_t ir_type = scc_ast2ir_type(ctx, decl->var.type);
// 创建分配节点
scc_ir_node_ref_t alloc_val_node =
scc_ir_value_ref_t alloc_val_node =
scc_ir_builder_alloca(&ctx->builder, ir_type, decl->name);
scc_hashtable_set(&ctx->node2ir, decl, (void *)(usize)alloc_val_node);
scc_hashtable_set(&ctx->decl2ir_ref, decl,
(void *)(usize)alloc_val_node);
// 如果有初始化表达式
if (!decl->var.init) {
break;
}
scc_ir_node_ref_t init_val_node =
scc_ir_value_ref_t init_val_node =
scc_ast2ir_expr(ctx, decl->var.init, false);
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node);
break;
@@ -581,15 +753,18 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
scc_ast_decl_t *param =
scc_vec_at(decl->func.type->function.params, i);
scc_ir_node_ref_t param_node_ref = scc_vec_at(func->params, i);
scc_ir_node_t *param_node =
scc_ir_module_get_node(ctx->builder.ctx.module, param_node_ref);
scc_ir_value_ref_t param_node_ref = scc_vec_at(func->params, i);
scc_ir_value_t *param_node = scc_ir_module_get_value(
ctx->builder.ctx.module, param_node_ref);
Assert(param_node != null);
param_node->name = param->name;
scc_hashtable_set(&ctx->node2ir, param,
scc_hashtable_set(&ctx->decl2ir_ref, param,
(void *)(usize)param_node_ref);
}
scc_ast2ir_stmt(ctx, decl->func.body);
// FIXME need ret for none return or other default ret
scc_ir_builder_ret_void(&ctx->builder);
scc_ir_builder_end_bblock(&ctx->builder);
scc_ir_builder_end_func(&ctx->builder);
break;
@@ -640,13 +815,13 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi,
Assert(ctx != null);
ctx->abi = abi;
scc_ir_builder_init(&ctx->builder, cprog);
scc_hashtable_init(&ctx->node2ir, scc_hash_node, scc_cmp_node);
scc_hashtable_init(&ctx->decl2ir_ref, scc_hash_node, scc_cmp_node);
scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp);
}
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) {
scc_ir_builder_drop(&ctx->builder);
scc_hashtable_drop(&ctx->node2ir);
scc_hashtable_drop(&ctx->decl2ir_ref);
scc_hashtable_drop(&ctx->symtab);
}

View File

@@ -39,16 +39,8 @@ scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder,
scc_ir_type_ref_t scc_ir_builder_type(scc_ir_builder_t *builder,
const scc_ir_type_t *type_desc);
// TODO
static inline scc_ir_node_ref_t
scc_ir_builder_const_int(scc_ir_builder_t *builder, scc_ir_type_ref_t type,
scc_ir_const_int_t value) {
scc_ir_node_t node;
scc_ir_node_init(&node, null, SCC_IR_NODE_CONST_INT);
node.data.const_int = value;
node.type = type;
return scc_ir_module_add_node(&builder->cprog->module, &node);
}
void scc_ir_builder_add_instr(scc_ir_builder_t *builder,
scc_ir_value_ref_t instr);
#define SCC_IR_BUILDER_TYPE_FUNC(scc_type) \
[[maybe_unused]] static inline scc_ir_type_ref_t \
@@ -76,6 +68,79 @@ SCC_IR_BUILDER_TYPE_FUNC(f32)
SCC_IR_BUILDER_TYPE_FUNC(f64)
SCC_IR_BUILDER_TYPE_FUNC(f128)
// TODO
static inline scc_ir_value_ref_t
scc_ir_builder_const_int(scc_ir_builder_t *builder, scc_ir_type_ref_t type,
scc_ir_const_int_t value) {
scc_ir_value_t node;
scc_ir_node_init(&node, null, SCC_IR_VALUE_TAG_CONST_INT);
node.data.const_int = value;
node.type = type;
return scc_ir_module_add_value(&builder->cprog->module, &node);
}
static inline scc_ir_value_ref_t
scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
usize len) {
scc_ir_type_ref_t u8_type = scc_ir_builder_type_u8(builder);
scc_ir_type_t array_type = {
.tag = SCC_IR_TYPE_ARRAY,
.data.array.base = u8_type,
.data.array.len = len - 1, // 包含 null 结尾
};
scc_ir_type_ref_t array_type_ref =
scc_ir_ctx_get_type(&builder->ctx, &array_type);
// 2. 创建指针类型:指向 array_type
scc_ir_type_t ptr_type = {.tag = SCC_IR_TYPE_PTR,
.data.pointer.base = u8_type};
scc_ir_type_ref_t ptr_type_ref =
scc_ir_ctx_get_type(&builder->ctx, &ptr_type);
// 5. 创建聚合节点
scc_ir_value_t const_array_value = {
.tag = SCC_IR_VALUE_TAG_CONST_ARRAY,
.type = array_type_ref,
.data.const_array.base_type = u8_type,
};
char *buff = scc_malloc(len - 1);
Assert(buff);
// FIXME content to real string
for (usize i = 1; i < len - 1; i++) {
buff[i - 1] = str[i];
}
buff[len - 2] = '\0';
scc_vec_unsafe_from_buffer(const_array_value.data.const_array.elements,
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);
// 3. 创建全局变量节点,类型为指针,初始值指向常量数组
char *name = scc_malloc(32);
// FIXME MAYBE MEMORY LEAK
scc_ir_value_ref_t global_value_ref = scc_ir_module_add_value(
builder->ctx.module, &(scc_ir_value_t){
.name = name,
.tag = SCC_IR_VALUE_TAG_GLOBAL_ALLOC,
.type = ptr_type_ref,
.data.global_alloc.value = const_array_ref,
});
scc_snprintf(name, 32, "$G%u", global_value_ref);
scc_vec_push(builder->cprog->global_vals, global_value_ref);
// scc_hashtable_insert(builder);
scc_ir_value_ref_t pointer_to_global_value = scc_ir_module_add_value(
builder->ctx.module, &(scc_ir_value_t){
.tag = SCC_IR_VALUE_TAG_GET_PTR,
.data.get_ptr.src_addr = global_value_ref,
.data.get_ptr.index = SCC_IR_VALUE_TAG_NULL,
});
scc_ir_builder_add_instr(builder, pointer_to_global_value);
return pointer_to_global_value;
}
/**
* @brief 开始构建函数
* @param func_ref 函数引用
@@ -118,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 设置当前基本块
*/
@@ -129,38 +195,38 @@ void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
* @param type 分配的类型
* @param name 变量名可为NULL
*/
scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name);
scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name);
scc_ir_node_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name, usize arg_idx);
scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name, usize arg_idx);
/**
* @brief 创建load指令
* @param ptr 指针操作数
*/
scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr);
scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_value_ref_t ptr);
/**
* @brief 创建store指令
* @param ptr 目标指针
* @param value 要存储的值
*/
scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t value);
scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
scc_ir_value_ref_t ptr,
scc_ir_value_ref_t value);
/**
* @brief 创建getptr指令指针运算
* @param ptr 基础指针
* @param index 索引值
*/
scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t index);
scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_value_ref_t ptr,
scc_ir_value_ref_t index);
/**
* @brief 创建二元运算指令
@@ -168,10 +234,10 @@ scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
* @param lhs 左操作数
* @param rhs 右操作数
*/
scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs);
scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_value_ref_t lhs,
scc_ir_value_ref_t rhs);
/**
* @brief 创建比较指令
@@ -179,16 +245,17 @@ scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
* @param lhs 左操作数
* @param rhs 右操作数
*/
scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op, scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs);
scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_value_ref_t lhs,
scc_ir_value_ref_t rhs);
/**
* @brief 创建跳转指令(无条件)
* @param target 目标基本块
*/
scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target);
scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target);
/**
* @brief 创建条件分支指令
@@ -196,10 +263,10 @@ scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
* @param true_target 条件为真时的目标
* @param false_target 条件为假时的目标
*/
scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_node_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target);
scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_value_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target);
/**
* @brief 创建函数调用指令
@@ -207,21 +274,21 @@ scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
* @param args 参数列表
* @param arg_count 参数数量
*/
scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_node_ref_t *args,
usize arg_count);
scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_value_ref_t *args,
usize arg_count);
/**
* @brief 创建返回指令(带返回值)
* @param value 返回值
*/
scc_ir_node_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_node_ref_t value);
scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_value_ref_t value);
/**
* @brief 创建返回指令void返回
*/
scc_ir_node_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder);
scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder);
#endif /* __SCC_IR_BUILDER_H__ */

View File

@@ -19,11 +19,6 @@ void scc_ir_ctx_drop(scc_ir_ctx_t *ctx);
scc_ir_type_ref_t scc_ir_ctx_get_type(scc_ir_ctx_t *ctx,
const scc_ir_type_t *type_desc);
// 获取唯一常量(例如整数常量)
// scc_ir_node_ref_t scc_ir_ctx_get_const_int(scc_ir_ctx_t *ctx,
// scc_ir_type_ref_t type, i64
// value);
// 注册函数声明,若已存在则返回已有引用
scc_ir_func_ref_t scc_ir_ctx_declare_func(scc_ir_ctx_t *ctx,
scc_ir_type_ref_t type,

View File

@@ -8,9 +8,11 @@
typedef unsigned int ir_handle_t;
typedef const char *scc_ir_label_t;
typedef struct scc_ir_node scc_ir_node_t;
typedef ir_handle_t scc_ir_node_ref_t;
typedef SCC_VEC(scc_ir_node_ref_t) scc_ir_node_ref_vec_t;
typedef SCC_VEC(u8) scc_ir_buffer_t;
typedef struct scc_ir_value scc_ir_value_t;
typedef ir_handle_t scc_ir_value_ref_t;
typedef SCC_VEC(scc_ir_value_ref_t) scc_ir_node_ref_vec_t;
typedef struct scc_ir_type scc_ir_type_t;
typedef ir_handle_t scc_ir_type_ref_t;
@@ -41,7 +43,6 @@ typedef enum scc_ir_type_tag {
SCC_IR_TYPE_f32,
SCC_IR_TYPE_f64,
SCC_IR_TYPE_f128,
SCC_IR_TYPE_PTR,
SCC_IR_TYPE_ARRAY,
SCC_IR_TYPE_FUNC,
@@ -84,26 +85,28 @@ struct scc_ir_func {
scc_ir_bblock_ref_vec_t bblocks;
};
typedef enum scc_ir_node_tag {
SCC_IR_NODE_NULL,
SCC_IR_NODE_CONST_INT,
SCC_IR_NODE_CONST_UINT,
SCC_IR_NODE_CONST_FLOAT,
SCC_IR_NODE_CONV, ///< 类型转换
SCC_IR_NODE_FUNC_ARG_REF, ///< 函数参数引用
SCC_IR_NODE_BLOCK_ARG_REF, ///< 基本块参数引用
SCC_IR_NODE_ALLOC, ///< 分配内存(stack)
SCC_IR_NODE_GLOBAL_ALLOC, ///< 全局分配(bss)
SCC_IR_NODE_LOAD, ///< 加载数据
SCC_IR_NODE_STORE, ///< 存储数据
SCC_IR_NODE_GET_PTR, ///< 获取指针
SCC_IR_NODE_GET_ELEM_PTR, ///< 获取元素指针(used by array)
SCC_IR_NODE_OP, ///< 二元运算
SCC_IR_NODE_BRANCH, ///< 有条件分支
SCC_IR_NODE_JUMP, ///< 无条件跳转
SCC_IR_NODE_CALL, ///< 调用函数
SCC_IR_NODE_RET, ///< 函数返回
} scc_ir_node_tag_t;
typedef enum scc_ir_value_tag {
SCC_IR_VALUE_TAG_NULL,
SCC_IR_VALUE_TAG_CONST_INT,
SCC_IR_VALUE_TAG_CONST_UINT,
SCC_IR_VALUE_TAG_CONST_FLOAT,
SCC_IR_VALUE_TAG_CONST_ARRAY,
SCC_IR_VALUE_TAG_AGGREGATE, ///< 聚合值
SCC_IR_VALUE_TAG_CONV, ///< 类型转换
SCC_IR_VALUE_TAG_FUNC_ARG_REF, ///< 函数参数引用
SCC_IR_VALUE_TAG_BLOCK_ARG_REF, ///< 基本块参数引用
SCC_IR_VALUE_TAG_ALLOC, ///< 分配内存
SCC_IR_VALUE_TAG_GLOBAL_ALLOC, ///< 全局分配
SCC_IR_VALUE_TAG_LOAD, ///< 加载数据
SCC_IR_VALUE_TAG_STORE, ///< 存储数据
SCC_IR_VALUE_TAG_GET_PTR, ///< 获取指针
SCC_IR_VALUE_TAG_GET_ELEM_PTR, ///< 获取元素指针
SCC_IR_VALUE_TAG_OP, ///< 二元运算
SCC_IR_VALUE_TAG_BRANCH, ///< 有条件分支
SCC_IR_VALUE_TAG_JUMP, ///< 无条件跳转
SCC_IR_VALUE_TAG_CALL, ///< 调用函数
SCC_IR_VALUE_TAG_RET, ///< 函数返回
} scc_ir_value_tag_t;
typedef enum {
/// Empty op for init or nop
@@ -172,49 +175,55 @@ typedef union {
u8 float_any[16];
} scc_ir_const_float_t;
struct scc_ir_node {
struct scc_ir_value {
scc_ir_type_ref_t type;
scc_ir_label_t name;
scc_ir_node_ref_vec_t used_by;
scc_ir_node_tag_t tag;
scc_ir_value_tag_t tag;
union {
scc_ir_const_int_t const_int;
scc_ir_const_uint_t const_uint;
scc_ir_const_float_t const_float;
// aggregate;
struct {
scc_ir_value_ref_t base_type;
scc_ir_buffer_t elements;
} const_array;
struct {
scc_ir_node_ref_vec_t elements;
} aggregate;
struct {
usize idx;
} arg_ref;
struct {
scc_ir_node_ref_vec_t elements;
scc_ir_value_ref_t value;
} global_alloc;
struct {
scc_ir_node_ref_t operand;
scc_ir_value_ref_t operand;
scc_ir_type_ref_t target_type; // 目标类型
enum { CONV_SEXT, CONV_ZEXT, CONV_TRUNC } conv_type;
} conv;
struct {
scc_ir_node_ref_t target;
scc_ir_value_ref_t target;
} load;
struct {
scc_ir_node_ref_t target;
scc_ir_node_ref_t value;
scc_ir_value_ref_t target;
scc_ir_value_ref_t value;
} store;
struct {
scc_ir_node_ref_t src_addr;
scc_ir_node_ref_t index;
scc_ir_value_ref_t src_addr;
scc_ir_value_ref_t index;
} get_ptr;
struct {
scc_ir_node_ref_t src_addr;
scc_ir_node_ref_t index;
scc_ir_value_ref_t src_addr;
scc_ir_value_ref_t index;
} get_elem_ptr;
struct {
scc_ir_op_type_t op;
scc_ir_node_ref_t lhs;
scc_ir_node_ref_t rhs;
scc_ir_value_ref_t lhs;
scc_ir_value_ref_t rhs;
} op;
struct {
scc_ir_node_ref_t cond;
scc_ir_value_ref_t cond;
scc_ir_bblock_ref_t true_bblock;
scc_ir_bblock_ref_t false_bblock;
} branch;
@@ -226,7 +235,7 @@ struct scc_ir_node {
scc_ir_node_ref_vec_t args;
} call;
struct {
scc_ir_node_ref_t ret_val;
scc_ir_value_ref_t ret_val;
} ret;
} data;
};

View File

@@ -2,17 +2,16 @@
#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_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref);
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);
void scc_ir_dump_bblock(scc_ir_dump_ctx_t *ctx, scc_ir_bblock_ref_t bblock_ref);
void scc_ir_dump_func(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref);

View File

@@ -0,0 +1,49 @@
#ifndef __SCC_IR_MODULE_H__
#define __SCC_IR_MODULE_H__
#include "ir_def.h"
#include <scc_hashtable.h>
typedef struct {
unsigned int value_uid;
unsigned int type_uid;
unsigned int bblock_uid;
unsigned int func_uid;
SCC_VEC(scc_ir_value_t) values;
SCC_VEC(scc_ir_type_t) types;
SCC_VEC(scc_ir_bblock_t) bblocks;
SCC_VEC(scc_ir_func_t) funcs;
// UID -> ref index
scc_hashtable_t uid2value;
scc_hashtable_t uid2type;
scc_hashtable_t uid2bblock;
scc_hashtable_t uid2func;
} scc_ir_module_t;
void scc_ir_module_init(scc_ir_module_t *ctx);
void scc_ir_module_drop(scc_ir_module_t *ctx);
scc_ir_type_ref_t scc_ir_module_add_type(scc_ir_module_t *ctx,
const scc_ir_type_t *type);
scc_ir_value_ref_t scc_ir_module_add_value(scc_ir_module_t *ctx,
const scc_ir_value_t *node);
scc_ir_bblock_ref_t scc_ir_module_add_bblock(scc_ir_module_t *ctx,
const scc_ir_bblock_t *bblock);
scc_ir_func_ref_t scc_ir_module_add_func(scc_ir_module_t *ctx,
const scc_ir_func_t *func);
scc_ir_type_t *scc_ir_module_get_type(scc_ir_module_t *ctx,
scc_ir_type_ref_t ref);
scc_ir_value_t *scc_ir_module_get_value(scc_ir_module_t *ctx,
scc_ir_value_ref_t ref);
scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx,
scc_ir_bblock_ref_t ref);
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

@@ -2,42 +2,7 @@
#define __SCC_IR_PROG_H__
#include "ir_def.h"
#include <scc_utils.h>
typedef struct {
unsigned int node_uid;
unsigned int type_uid;
unsigned int bblock_uid;
unsigned int func_uid;
SCC_VEC(scc_ir_node_t) nodes;
SCC_VEC(scc_ir_type_t) types;
SCC_VEC(scc_ir_bblock_t) bblocks;
SCC_VEC(scc_ir_func_t) funcs;
// UID -> ref index
scc_hashtable_t uid2nodes;
scc_hashtable_t uid2types;
scc_hashtable_t uid2bblocks;
scc_hashtable_t uid2funcs;
} scc_ir_module_t;
void scc_ir_module_init(scc_ir_module_t *ctx);
void scc_ir_module_drop(scc_ir_module_t *ctx);
scc_ir_type_ref_t scc_ir_module_add_type(scc_ir_module_t *ctx,
const scc_ir_type_t *type);
scc_ir_node_ref_t scc_ir_module_add_node(scc_ir_module_t *ctx,
const scc_ir_node_t *node);
scc_ir_bblock_ref_t scc_ir_module_add_bblock(scc_ir_module_t *ctx,
const scc_ir_bblock_t *bblock);
scc_ir_func_ref_t scc_ir_module_add_func(scc_ir_module_t *ctx,
const scc_ir_func_t *func);
scc_ir_type_t *scc_ir_module_get_type(scc_ir_module_t *ctx,
scc_ir_type_ref_t ref);
scc_ir_node_t *scc_ir_module_get_node(scc_ir_module_t *ctx,
scc_ir_node_ref_t ref);
scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx,
scc_ir_bblock_ref_t ref);
scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx,
scc_ir_func_ref_t ref);
#include "ir_module.h"
typedef struct scc_ir_cprog {
scc_ir_module_t module;

View File

@@ -9,7 +9,7 @@ void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label);
void scc_ir_func_init(scc_ir_func_t *in, const char *name);
// node name can be null ptr
void scc_ir_node_init(scc_ir_node_t *in, const char *name,
scc_ir_node_tag_t tag);
void scc_ir_node_init(scc_ir_value_t *in, const char *name,
scc_ir_value_tag_t tag);
#endif /* __SCC_IR_H__ */

View File

@@ -56,22 +56,25 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
return;
}
scc_vec_foreach(func_type->data.function.params, i) {
scc_ir_type_ref_t param_type =
scc_vec_at(func_type->data.function.params, i);
scc_ir_type_ref_vec_t params = func_type->data.function.params;
func_type = null;
scc_vec_foreach(params, i) {
scc_ir_type_ref_t param_type = scc_vec_at(params, i);
scc_ir_node_t param_node = {0};
param_node.tag = SCC_IR_NODE_FUNC_ARG_REF; // 参数节点标记
param_node.type = param_type;
scc_ir_value_t param_node = {0};
param_node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF; // 参数节点标记
param_node.type = scc_ir_module_add_type(
GET_MODULE(builder),
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR,
.data.pointer.base = param_type});
param_node.name = param_names ? param_names[i] : null;
param_node.data.arg_ref.idx = i;
scc_vec_init(param_node.used_by);
scc_ir_node_ref_t param_ref =
scc_ir_module_add_node(GET_MODULE(builder), &param_node);
scc_ir_value_ref_t param_ref =
scc_ir_module_add_value(GET_MODULE(builder), &param_node);
scc_vec_push(func_ptr->params, param_ref);
}
return;
}
@@ -129,29 +132,33 @@ void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
builder->current_bblock = bblock;
}
static void scc_ir_builder_add_instr(scc_ir_builder_t *builder,
scc_ir_node_ref_t node) {
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 =
scc_ir_module_get_bblock(GET_MODULE(builder), builder->current_bblock);
if (current_bblock) {
scc_vec_push(current_bblock->instrs, node);
scc_vec_push(current_bblock->instrs, instr);
} else {
LOG_ERROR("Current basic block is not set");
}
}
scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name) {
scc_ir_node_t alloc_node = {0};
alloc_node.tag = SCC_IR_NODE_ALLOC;
scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name) {
scc_ir_value_t alloc_node = {0};
alloc_node.tag = SCC_IR_VALUE_TAG_ALLOC;
alloc_node.type = scc_ir_module_add_type(
GET_MODULE(builder),
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR, .data.pointer.base = type});
alloc_node.name = name;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &alloc_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &alloc_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -159,31 +166,32 @@ scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name, usize arg_idx) {
scc_ir_node_t node = {0};
node.tag = SCC_IR_NODE_FUNC_ARG_REF;
scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name,
usize arg_idx) {
scc_ir_value_t node = {0};
node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF;
node.type = type;
node.name = name;
node.data.arg_ref.idx = arg_idx;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_node_ref_t target) {
scc_ir_node_t load_node = {0};
load_node.tag = SCC_IR_NODE_LOAD;
scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_value_ref_t target) {
scc_ir_value_t load_node = {0};
load_node.tag = SCC_IR_VALUE_TAG_LOAD;
load_node.data.load.target = target;
// 设置类型为指针指向的类型
scc_ir_node_t *ptr_node =
scc_ir_module_get_node(GET_MODULE(builder), target);
scc_ir_value_t *ptr_node =
scc_ir_module_get_value(GET_MODULE(builder), target);
if (ptr_node) {
scc_ir_type_t *ptr_type =
scc_ir_module_get_type(GET_MODULE(builder), ptr_node->type);
@@ -192,8 +200,8 @@ scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
}
}
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &load_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &load_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -201,16 +209,17 @@ scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
scc_ir_node_ref_t target,
scc_ir_node_ref_t value) {
scc_ir_node_t store_node = {0};
store_node.tag = SCC_IR_NODE_STORE;
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;
store_node.data.store.value = value;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &store_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &store_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -218,23 +227,23 @@ scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_node_ref_t target,
scc_ir_node_ref_t index) {
scc_ir_node_t get_ptr_node = {0};
get_ptr_node.tag = SCC_IR_NODE_GET_PTR;
scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_value_ref_t target,
scc_ir_value_ref_t index) {
scc_ir_value_t get_ptr_node = {0};
get_ptr_node.tag = SCC_IR_VALUE_TAG_GET_PTR;
get_ptr_node.data.get_ptr.src_addr = target;
get_ptr_node.data.get_ptr.index = index;
// 类型应与源地址相同(都是指针)
scc_ir_node_t *src_node =
scc_ir_module_get_node(GET_MODULE(builder), target);
scc_ir_value_t *src_node =
scc_ir_module_get_value(GET_MODULE(builder), target);
if (src_node) {
get_ptr_node.type = src_node->type;
}
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &get_ptr_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &get_ptr_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -242,24 +251,25 @@ scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs) {
scc_ir_node_t binop_node = {0};
binop_node.tag = SCC_IR_NODE_OP;
scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_value_ref_t lhs,
scc_ir_value_ref_t rhs) {
scc_ir_value_t binop_node = {0};
binop_node.tag = SCC_IR_VALUE_TAG_OP;
binop_node.data.op.op = op;
binop_node.data.op.lhs = lhs;
binop_node.data.op.rhs = rhs;
// 类型通常与操作数相同(对于算术运算)
scc_ir_node_t *lhs_node = scc_ir_module_get_node(GET_MODULE(builder), lhs);
scc_ir_value_t *lhs_node =
scc_ir_module_get_value(GET_MODULE(builder), lhs);
if (lhs_node) {
binop_node.type = lhs_node->type;
}
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &binop_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &binop_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -267,11 +277,12 @@ scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op, scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs) {
scc_ir_node_t cmp_node = {0};
cmp_node.tag = SCC_IR_NODE_OP;
scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_value_ref_t lhs,
scc_ir_value_ref_t rhs) {
scc_ir_value_t cmp_node = {0};
cmp_node.tag = SCC_IR_VALUE_TAG_OP;
cmp_node.data.op.op = op;
cmp_node.data.op.lhs = lhs;
cmp_node.data.op.rhs = rhs;
@@ -280,8 +291,8 @@ scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
cmp_node.type =
0; // FIXME scc_ir_module_get_builtin_i32(GET_MODULE(builder));
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &cmp_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &cmp_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -289,14 +300,14 @@ scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target) {
scc_ir_node_t jump_node = {0};
jump_node.tag = SCC_IR_NODE_JUMP;
scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target) {
scc_ir_value_t jump_node = {0};
jump_node.tag = SCC_IR_VALUE_TAG_JUMP;
jump_node.data.jump.target_bblock = target;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &jump_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &jump_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -304,18 +315,18 @@ scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_node_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target) {
scc_ir_node_t branch_node = {0};
branch_node.tag = SCC_IR_NODE_BRANCH;
scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_value_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target) {
scc_ir_value_t branch_node = {0};
branch_node.tag = SCC_IR_VALUE_TAG_BRANCH;
branch_node.data.branch.cond = cond;
branch_node.data.branch.true_bblock = true_target;
branch_node.data.branch.false_bblock = false_target;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &branch_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &branch_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -323,12 +334,12 @@ scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_node_ref_t *args,
usize arg_count) {
scc_ir_node_t call_node = {0};
call_node.tag = SCC_IR_NODE_CALL;
scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_value_ref_t *args,
usize arg_count) {
scc_ir_value_t call_node = {0};
call_node.tag = SCC_IR_VALUE_TAG_CALL;
call_node.data.call.callee = callee;
scc_vec_init(call_node.data.call.args);
@@ -347,8 +358,8 @@ scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
}
}
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &call_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &call_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -356,14 +367,14 @@ scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_node_ref_t value) {
scc_ir_node_t ret_node = {0};
ret_node.tag = SCC_IR_NODE_RET;
scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_value_ref_t value) {
scc_ir_value_t ret_node = {0};
ret_node.tag = SCC_IR_VALUE_TAG_RET;
ret_node.data.ret.ret_val = value;
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &ret_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
@@ -371,13 +382,13 @@ scc_ir_node_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
scc_ir_node_t ret_node = {0};
ret_node.tag = SCC_IR_NODE_RET;
scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
scc_ir_value_t ret_node = {0};
ret_node.tag = SCC_IR_VALUE_TAG_RET;
ret_node.data.ret.ret_val = 0; // 无返回值
scc_ir_node_ref_t node_ref =
scc_ir_module_add_node(GET_MODULE(builder), &ret_node);
scc_ir_value_ref_t node_ref =
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);

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;
@@ -149,10 +149,10 @@ scc_ir_type_ref_t scc_ir_ctx_get_type(scc_ir_ctx_t *ctx,
return new_ref;
}
// scc_ir_node_ref_t scc_ir_ctx_get_const_int(scc_ir_ctx_t *ctx,
// scc_ir_value_ref_t scc_ir_ctx_get_const_int(scc_ir_ctx_t *ctx,
// scc_ir_type_ref_t type, i64 value)
// {
// return scc_ir_node_ref_t();
// return scc_ir_value_ref_t();
// }
scc_ir_func_ref_t scc_ir_ctx_declare_func(scc_ir_ctx_t *ctx,

File diff suppressed because it is too large Load Diff

137
libs/ir/src/ir_module.c Normal file
View File

@@ -0,0 +1,137 @@
#include <ir_module.h>
static u32 hash_key(const void *key) { return (u32)(usize)key; }
static int cmp_key(const void *key1, const void *key2) {
return (u32)(usize)key1 != (u32)(usize)key2;
}
void scc_ir_module_init(scc_ir_module_t *ctx) {
scc_vec_init(ctx->values);
scc_vec_init(ctx->types);
scc_vec_init(ctx->bblocks);
scc_vec_init(ctx->funcs);
scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2type, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2bblock, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2func, hash_key, cmp_key);
// 预留UID 0 作为无效引用
ctx->value_uid = 1;
ctx->type_uid = 1;
ctx->bblock_uid = 1;
ctx->func_uid = 1;
}
void scc_ir_module_drop(scc_ir_module_t *ctx) {
// 释放所有实体的内部内存
for (usize i = 0; i < ctx->values.size; i++) {
scc_ir_value_t *node = &ctx->values.data[i];
scc_vec_free(node->used_by);
if (node->tag == SCC_IR_VALUE_TAG_CALL) {
scc_vec_free(node->data.call.args);
}
}
for (usize i = 0; i < ctx->types.size; i++) {
scc_ir_type_t *type = &ctx->types.data[i];
if (type->tag == SCC_IR_TYPE_FUNC) {
scc_vec_free(type->data.function.params);
}
}
for (usize i = 0; i < ctx->bblocks.size; i++) {
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
scc_vec_free(bblock->instrs);
}
for (usize i = 0; i < ctx->funcs.size; i++) {
scc_ir_func_t *func = &ctx->funcs.data[i];
scc_vec_free(func->params);
scc_vec_free(func->bblocks);
}
scc_vec_free(ctx->values);
scc_vec_free(ctx->types);
scc_vec_free(ctx->bblocks);
scc_vec_free(ctx->funcs);
scc_hashtable_drop(&ctx->uid2value);
scc_hashtable_drop(&ctx->uid2type);
scc_hashtable_drop(&ctx->uid2bblock);
scc_hashtable_drop(&ctx->uid2func);
}
// 辅助宏:创建实体并添加到哈希表
#define CREATE_ENTITY(ctx, vec, uid, data, hashtable) \
do { \
/* 分配新UID */ \
unsigned new_uid = (ctx)->uid++; \
/* 添加到向量 */ \
scc_vec_push((vec), *(data)); \
/* 添加到哈希表 */ \
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
(void *)(usize)(scc_vec_size(vec) - 1)); \
return new_uid; \
} while (0)
scc_ir_type_ref_t scc_ir_module_add_type(scc_ir_module_t *ctx,
const scc_ir_type_t *type) {
CREATE_ENTITY(ctx, ctx->types, type_uid, type, uid2type);
}
scc_ir_value_ref_t scc_ir_module_add_value(scc_ir_module_t *ctx,
const scc_ir_value_t *node) {
CREATE_ENTITY(ctx, ctx->values, value_uid, node, uid2value);
}
scc_ir_bblock_ref_t scc_ir_module_add_bblock(scc_ir_module_t *ctx,
const scc_ir_bblock_t *bblock) {
CREATE_ENTITY(ctx, ctx->bblocks, bblock_uid, bblock, uid2bblock);
}
scc_ir_func_ref_t scc_ir_module_add_func(scc_ir_module_t *ctx,
const scc_ir_func_t *func) {
CREATE_ENTITY(ctx, ctx->funcs, func_uid, func, uid2func);
}
// 辅助宏:从哈希表获取索引
#define GET_ENTITY_INDEX(ctx, ref, hashtable) \
((usize)scc_hashtable_get(&(ctx)->hashtable, (void *)(usize)ref))
scc_ir_type_t *scc_ir_module_get_type(scc_ir_module_t *ctx,
scc_ir_type_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2type);
if (idx >= ctx->types.size)
return null;
return &ctx->types.data[idx];
}
scc_ir_value_t *scc_ir_module_get_value(scc_ir_module_t *ctx,
scc_ir_value_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2value);
if (idx >= ctx->values.size)
return null;
return &ctx->values.data[idx];
}
scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx,
scc_ir_bblock_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2bblock);
if (idx >= ctx->bblocks.size)
return null;
return &ctx->bblocks.data[idx];
}
scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx,
scc_ir_func_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2func);
if (idx >= ctx->funcs.size)
return null;
return &ctx->funcs.data[idx];
}

View File

@@ -13,139 +13,3 @@ void scc_ir_cprog_drop(scc_ir_cprog_t *in) {
scc_vec_free(in->global_vals);
scc_ir_module_drop(&in->module);
}
static u32 hash_key(const void *key) { return (u32)(usize)key; }
static int cmp_key(const void *key1, const void *key2) {
return (u32)(usize)key1 != (u32)(usize)key2;
}
void scc_ir_module_init(scc_ir_module_t *ctx) {
scc_vec_init(ctx->nodes);
scc_vec_init(ctx->types);
scc_vec_init(ctx->bblocks);
scc_vec_init(ctx->funcs);
scc_hashtable_init(&ctx->uid2nodes, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2types, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2bblocks, hash_key, cmp_key);
scc_hashtable_init(&ctx->uid2funcs, hash_key, cmp_key);
// 预留UID 0 作为无效引用
ctx->node_uid = 1;
ctx->type_uid = 1;
ctx->bblock_uid = 1;
ctx->func_uid = 1;
}
void scc_ir_module_drop(scc_ir_module_t *ctx) {
// 释放所有实体的内部内存
for (usize i = 0; i < ctx->nodes.size; i++) {
scc_ir_node_t *node = &ctx->nodes.data[i];
scc_vec_free(node->used_by);
if (node->tag == SCC_IR_NODE_CALL) {
scc_vec_free(node->data.call.args);
}
}
for (usize i = 0; i < ctx->types.size; i++) {
scc_ir_type_t *type = &ctx->types.data[i];
if (type->tag == SCC_IR_TYPE_FUNC) {
scc_vec_free(type->data.function.params);
}
}
for (usize i = 0; i < ctx->bblocks.size; i++) {
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
scc_vec_free(bblock->instrs);
}
for (usize i = 0; i < ctx->funcs.size; i++) {
scc_ir_func_t *func = &ctx->funcs.data[i];
scc_vec_free(func->params);
scc_vec_free(func->bblocks);
}
scc_vec_free(ctx->nodes);
scc_vec_free(ctx->types);
scc_vec_free(ctx->bblocks);
scc_vec_free(ctx->funcs);
scc_hashtable_drop(&ctx->uid2nodes);
scc_hashtable_drop(&ctx->uid2types);
scc_hashtable_drop(&ctx->uid2bblocks);
scc_hashtable_drop(&ctx->uid2funcs);
}
// 辅助宏:创建实体并添加到哈希表
#define CREATE_ENTITY(ctx, vec, uid, data, hashtable) \
do { \
/* 分配新UID */ \
unsigned new_uid = (ctx)->uid++; \
/* 添加到向量 */ \
scc_vec_push((vec), *(data)); \
/* 添加到哈希表 */ \
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
(void *)(usize)(scc_vec_size(vec) - 1)); \
return new_uid; \
} while (0)
scc_ir_type_ref_t scc_ir_module_add_type(scc_ir_module_t *ctx,
const scc_ir_type_t *type) {
CREATE_ENTITY(ctx, ctx->types, type_uid, type, uid2types);
}
scc_ir_node_ref_t scc_ir_module_add_node(scc_ir_module_t *ctx,
const scc_ir_node_t *node) {
CREATE_ENTITY(ctx, ctx->nodes, node_uid, node, uid2nodes);
}
scc_ir_bblock_ref_t scc_ir_module_add_bblock(scc_ir_module_t *ctx,
const scc_ir_bblock_t *bblock) {
CREATE_ENTITY(ctx, ctx->bblocks, bblock_uid, bblock, uid2bblocks);
}
scc_ir_func_ref_t scc_ir_module_add_func(scc_ir_module_t *ctx,
const scc_ir_func_t *func) {
CREATE_ENTITY(ctx, ctx->funcs, func_uid, func, uid2funcs);
}
// 辅助宏:从哈希表获取索引
#define GET_ENTITY_INDEX(ctx, ref, hashtable) \
((usize)scc_hashtable_get(&(ctx)->hashtable, (void *)(usize)ref))
scc_ir_type_t *scc_ir_module_get_type(scc_ir_module_t *ctx,
scc_ir_type_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2types);
if (idx >= ctx->types.size)
return null;
return &ctx->types.data[idx];
}
scc_ir_node_t *scc_ir_module_get_node(scc_ir_module_t *ctx,
scc_ir_node_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2nodes);
if (idx >= ctx->nodes.size)
return null;
return &ctx->nodes.data[idx];
}
scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx,
scc_ir_bblock_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2bblocks);
if (idx >= ctx->bblocks.size)
return null;
return &ctx->bblocks.data[idx];
}
scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx,
scc_ir_func_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2funcs);
if (idx >= ctx->funcs.size)
return null;
return &ctx->funcs.data[idx];
}

View File

@@ -55,8 +55,8 @@ void scc_ir_func_init(scc_ir_func_t *in, const char *name) {
scc_vec_init(in->params);
}
void scc_ir_node_init(scc_ir_node_t *in, const char *name,
scc_ir_node_tag_t tag) {
void scc_ir_node_init(scc_ir_value_t *in, const char *name,
scc_ir_value_tag_t tag) {
Assert(in != null);
in->name = name;
in->tag = tag;
@@ -64,44 +64,44 @@ void scc_ir_node_init(scc_ir_node_t *in, const char *name,
in->type = 0;
switch (tag) {
case SCC_IR_NODE_NULL:
case SCC_IR_VALUE_TAG_NULL:
break;
case SCC_IR_NODE_CONST_INT:
case SCC_IR_VALUE_TAG_CONST_INT:
// TODO
in->data.const_int.int64 = 0;
break;
case SCC_IR_NODE_ALLOC:
case SCC_IR_VALUE_TAG_ALLOC:
// TODO();
break;
case SCC_IR_NODE_LOAD:
case SCC_IR_VALUE_TAG_LOAD:
in->data.load.target = 0;
break;
case SCC_IR_NODE_STORE:
case SCC_IR_VALUE_TAG_STORE:
in->data.store.target = 0;
in->data.store.value = 0;
break;
case SCC_IR_NODE_GET_PTR:
case SCC_IR_VALUE_TAG_GET_PTR:
in->data.get_ptr.src_addr = 0;
in->data.get_ptr.index = 0;
break;
case SCC_IR_NODE_OP:
case SCC_IR_VALUE_TAG_OP:
in->data.op.op = SCC_IR_OP_EMPTY;
in->data.op.lhs = 0;
in->data.op.rhs = 0;
break;
case SCC_IR_NODE_BRANCH:
case SCC_IR_VALUE_TAG_BRANCH:
in->data.branch.cond = 0;
in->data.branch.true_bblock = 0;
in->data.branch.false_bblock = 0;
break;
case SCC_IR_NODE_JUMP:
case SCC_IR_VALUE_TAG_JUMP:
in->data.jump.target_bblock = 0;
break;
case SCC_IR_NODE_CALL:
case SCC_IR_VALUE_TAG_CALL:
scc_vec_init(in->data.call.args);
in->data.call.callee = 0;
break;
case SCC_IR_NODE_RET:
case SCC_IR_VALUE_TAG_RET:
in->data.ret.ret_val = 0;
break;
default:

View File

@@ -0,0 +1,27 @@
#ifndef __SCC_FRAME_MANAGER_H__
#define __SCC_FRAME_MANAGER_H__
typedef struct frame_manager frame_manager_t;
// 初始化帧管理器,传入 ABI 参数(影子空间大小、栈对齐等)
void frame_manager_init(frame_manager_t *fm, int shadow_space, int align);
// 分配一个栈槽用于局部变量或临时值返回虚拟槽索引从0开始
int frame_alloc_slot(frame_manager_t *fm, int size);
// 分配一个保存的寄存器槽(用于被调用者保存的寄存器),返回虚拟槽索引
int frame_alloc_saved_reg(frame_manager_t *fm, int reg_width);
// 计算最终栈帧总大小(已对齐)
int frame_total_size(frame_manager_t *fm);
// 将虚拟槽索引转换为相对于 RBP 的偏移(正数,表示从 RBP 向下的距离)
int frame_slot_offset(frame_manager_t *fm, int slot_idx);
// 获取影子空间大小(固定)
int frame_shadow_space(frame_manager_t *fm);
// 获取保存寄存器区域的总大小
int frame_saved_reg_size(frame_manager_t *fm);
#endif /* __SCC_FRAME_MANAGER_H__ */

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 {
@@ -36,6 +37,7 @@ typedef struct scc_reg_alloc {
int gpr_callee_saved; ///< 函数必须保护这些寄存器的值.
scc_reg_alloc_func_t reg_alloc_func;
int alloc_stack_size;
int init_stack_size;
} scc_reg_alloc_t;
#define scc_reg_alloc(ctx, func) ((ctx)->reg_alloc_func(ctx, func))

View File

View File

@@ -5,10 +5,28 @@
#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_node_ref_t node_ref) {
scc_ir_value_ref_t node_ref) {
Assert(ctx != null && loc != null);
scc_ir_node_t *node = scc_ir_module_get_node(GET_MODULE(ctx), node_ref);
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (node == null) {
LOG_FATAL("invalid node ref");
UNREACHABLE();
@@ -16,7 +34,7 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
}
usize idx = 0;
switch (node->tag) {
case SCC_IR_NODE_CONST_INT:
case SCC_IR_VALUE_TAG_CONST_INT:
scc_ir_type_t *type =
scc_ir_module_get_type(GET_MODULE(ctx), node->type);
Assert(type != 0);
@@ -26,22 +44,26 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
.idx = (usize)node->data.const_int.int32,
};
return;
case SCC_IR_NODE_CONST_UINT:
case SCC_IR_NODE_CONST_FLOAT:
case SCC_IR_VALUE_TAG_CONST_UINT:
case SCC_IR_VALUE_TAG_CONST_FLOAT:
TODO();
break;
case SCC_IR_NODE_FUNC_ARG_REF: {
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
TODO();
break;
case SCC_IR_VALUE_TAG_FUNC_ARG_REF: {
scc_ir_type_t *type =
scc_ir_module_get_type(GET_MODULE(ctx), node->type);
Assert(type != 0);
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);
@@ -69,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");
}
@@ -90,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;
@@ -97,58 +131,147 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc,
}
// 临时存储待修补条目
typedef struct {
typedef struct patch {
usize pos;
usize target_bb_ref;
} patch_t;
typedef SCC_VEC(patch_t) patch_vec_t;
static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
patch_vec_t *patches) {
scc_ir_node_t *node = scc_ir_module_get_node(GET_MODULE(ctx), node_ref);
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
patch_vec_t *patches) {
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
if (node == null) {
LOG_ERROR("invalid node ref");
return;
}
switch (node->tag) {
case SCC_IR_NODE_CONV: ///< 类型转换
case SCC_IR_VALUE_TAG_CONV: ///< 类型转换
LOG_FATAL("Unsupported node type: %d", node->tag);
break;
///< 函数参数引用
case SCC_IR_NODE_FUNC_ARG_REF:
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
///< ABI
break;
case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用
case SCC_IR_NODE_ALLOC: ///< 分配内存(stack)
case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss)
case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用
break;
case SCC_IR_NODE_LOAD: ///< 加载数据
{
case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack)
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss
break;
///< 加载数据
case SCC_IR_VALUE_TAG_LOAD: {
// node->data.load.target
scc_reg_loc_t from;
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 if (width == 8) { // 8
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
SCC_AMD64_RCX);
} else {
UNREACHABLE();
}
// 存储结果
store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX);
break;
}
case SCC_IR_NODE_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);
///< 存储数据
case SCC_IR_VALUE_TAG_STORE: {
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;
}
case SCC_IR_NODE_GET_PTR: ///< 获取指针
case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array)
///< 获取指针
case SCC_IR_VALUE_TAG_GET_PTR: {
scc_reg_loc_t loc;
scc_ir_value_t *src_addr = scc_ir_module_get_value(
GET_MODULE(ctx), node->data.get_ptr.src_addr);
Assert(src_addr != null);
if (src_addr->tag != SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
Panic();
}
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
usize sym_idx =
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
Assert(sym_idx != 0);
sccf_builder_add_reloc(
ctx->builder, (sccf_reloc_t){
.reloc_type = SCCF_RELOC_TYPE_REL,
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_DATA,
.sym_idx = sym_idx,
});
parse_location(ctx, &loc, node_ref);
store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RAX);
break;
}
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array)
TODO();
///< 二元运算
case SCC_IR_NODE_OP: {
case SCC_IR_VALUE_TAG_OP: {
scc_reg_loc_t loc_lhs;
parse_location(ctx, &loc_lhs, node->data.op.lhs);
scc_reg_loc_t loc_rhs;
@@ -161,6 +284,9 @@ static void parse_node(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);
@@ -172,16 +298,30 @@ static void parse_node(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);
@@ -239,7 +379,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
break;
}
///< 有条件分支
case SCC_IR_NODE_BRANCH: {
case SCC_IR_VALUE_TAG_BRANCH: {
scc_reg_loc_t loc;
parse_location(ctx, &loc, node->data.branch.cond);
// (void)loc;
@@ -259,7 +399,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
break;
}
///< 无条件跳转
case SCC_IR_NODE_JUMP: {
case SCC_IR_VALUE_TAG_JUMP: {
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
usize pos = scc_vec_size(ctx->sect_mcode.mcode);
patch_t patch = {.pos = pos,
@@ -268,7 +408,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
break;
}
///< 调用函数
case SCC_IR_NODE_CALL: {
case SCC_IR_VALUE_TAG_CALL: {
scc_reg_loc_t loc;
/*
ABI
@@ -301,7 +441,12 @@ static void parse_node(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(
@@ -326,7 +471,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
break;
}
///< 函数返回
case SCC_IR_NODE_RET: {
case SCC_IR_VALUE_TAG_RET: {
if (node->data.ret.ret_val) {
scc_reg_loc_t loc;
parse_location(ctx, &loc, node->data.ret.ret_val);
@@ -349,8 +494,8 @@ static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock,
// 打印基本块中的每条指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, i);
parse_node(ctx, node_ref, patches);
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i);
parse_value(ctx, node_ref, patches);
}
}
@@ -360,6 +505,8 @@ static int equal_func(const void *key1, const void *key2) {
}
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
// FIXME using API instead
ctx->reg_alloc.init_stack_size = 8;
ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func);
// 对齐到 16 字节
// FIXME
@@ -385,9 +532,9 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
SCC_AMD64_RSP, ctx->stack_size);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
// scc_ir_node_t *param =
// scc_ir_module_get_node(GET_MODULE(ctx), );
scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i);
// scc_ir_value_t *param =
// scc_ir_module_get_value(GET_MODULE(ctx), );
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
parse_location(ctx, &loc, node_ref);
if (i == 0) {
store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RCX);
@@ -438,8 +585,36 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack,
GET_MODULE(ctx));
sccf_sect_data_t data_section;
scc_vec_init(data_section);
scc_vec_foreach(ctx->cprog->global_vals, i) {
scc_ir_value_t *galloc = scc_ir_module_get_value(
GET_MODULE(ctx), scc_vec_at(ctx->cprog->global_vals, i));
Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC);
scc_ir_value_t *value = scc_ir_module_get_value(
GET_MODULE(ctx), galloc->data.global_alloc.value);
Assert(value != null);
sccf_sym_t sym = (sccf_sym_t){
.sccf_sect_offset = scc_vec_size(ctx->sect_data),
.sccf_sect_type = SCCF_SECT_DATA,
.sccf_sym_bind =
galloc->name ? SCCF_SYM_BIND_GLOBAL : SCCF_SYM_BIND_LOCAL,
.sccf_sym_size =
4, // FIXME on windows using rel32, on linux using ?
.sccf_sym_type = SCCF_SYM_TYPE_DATA,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
scc_vec_foreach(value->data.const_array.elements, j) {
scc_vec_push(data_section,
scc_vec_at(value->data.const_array.elements, j));
}
usize sym_idx =
sccf_builder_add_symbol(ctx->builder, galloc->name, &sym);
Assert(sym_idx != 0);
}
scc_vec_foreach(ctx->cprog->func_decls, i) {
scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i);
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
@@ -471,7 +646,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
}
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
@@ -494,15 +669,16 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL);
Assert(sym->sccf_sect_type == SCCF_SECT_CODE);
Assert(sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC);
i64 target_off = sym->sccf_sect_offset;
i64 next_off = reloc->offset + reloc->addend;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(i32 *)(&buf[reloc->offset]) = rel;
if (sym->sccf_sect_type == SCCF_SECT_CODE &&
sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC) {
i64 target_off = sym->sccf_sect_offset;
i64 next_off = reloc->offset + reloc->addend;
i32 rel = (i32)(target_off - next_off);
// FIXME 写入到指令的偏移字段(小端)
*(i32 *)(&buf[reloc->offset]) = rel;
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
}
}
}
@@ -511,8 +687,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_vec_unsafe_get_data(ctx->sect_mcode.mcode),
scc_vec_size(ctx->sect_mcode.mcode));
sccf_builder_add_text_section(ctx->builder, &text_section);
sccf_sect_data_t data_section;
scc_vec_init(data_section);
sccf_builder_add_data_section(ctx->builder, &data_section);
// FIXME
ctx->builder->entry_symbol_name = "main";

View File

@@ -13,20 +13,21 @@ void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t func,
ctx->reg_alloc_func = func;
ctx->alloc_stack_size = 0;
ctx->init_stack_size = 0;
scc_vec_init(ctx->reg_loc_vec);
scc_hashtable_init(&ctx->node_ref2reg_loc, hash_func, equal_func);
}
scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
scc_ir_func_t *func) {
ctx->alloc_stack_size = 0;
ctx->alloc_stack_size = ctx->init_stack_size;
scc_hashtable_drop(&ctx->node_ref2reg_loc);
scc_vec_free(ctx->reg_loc_vec);
scc_vec_init(ctx->reg_loc_vec);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i);
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
loc.kind = SCC_REG_KIND_FUNC_ARG;
loc.idx = i;
ctx->alloc_stack_size += 8;
@@ -40,16 +41,16 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
scc_ir_module_get_bblock(ctx->ir_module, bblock_ref);
Assert(bblock != null);
scc_vec_foreach(bblock->instrs, j) {
scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, j);
scc_ir_node_t *node =
scc_ir_module_get_node(ctx->ir_module, node_ref);
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, j);
scc_ir_value_t *node =
scc_ir_module_get_value(ctx->ir_module, node_ref);
Assert(node != null);
loc.kind = SCC_REG_KIND_UNDEF;
switch (node->tag) {
case SCC_IR_NODE_LOAD:
case SCC_IR_NODE_OP:
case SCC_IR_NODE_ALLOC: {
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: {
loc.kind = SCC_REG_KIND_STACK;
loc.idx = ctx->alloc_stack_size;
@@ -60,7 +61,21 @@ 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_NODE_CALL: {
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 =
scc_ir_module_get_type(ctx->ir_module, 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

@@ -52,6 +52,8 @@
#define SCC_AMD64_COND_LE 14 // less or equal (signed)
#define SCC_AMD64_COND_G 15 // greater (signed)
#define SCC_MCODE_FUNC [[maybe_unused]] static inline
// ==================== REX 前缀辅助 ====================
/**
* @brief 生成 REX 前缀(若不为 0x40 则写入)
@@ -62,8 +64,8 @@
* @param x REX.X 位
* @param b REX.B 位
*/
static inline void scc_mcode_amd64_rex(scc_mcode_t *mcode, u8 w, u8 r, u8 x,
u8 b) {
SCC_MCODE_FUNC void scc_mcode_amd64_rex(scc_mcode_t *mcode, u8 w, u8 r, u8 x,
u8 b) {
u8 rex = 0x40 | (w << 3) | (r << 2) | (x << 1) | b;
if (rex != 0x40)
scc_mcode_add_u8(mcode, rex);
@@ -82,9 +84,9 @@ static inline void scc_mcode_amd64_rex(scc_mcode_t *mcode, u8 w, u8 r, u8 x,
* @param p_src_low 输出 src 的低 3 位
* @return 是否需要写入 REX 前缀0 表示不需要)
*/
static inline int scc_mcode_amd64_prepare_rex(int dst_reg, int src_reg,
int use_w, u8 *p_rex,
u8 *p_dst_low, u8 *p_src_low) {
SCC_MCODE_FUNC int scc_mcode_amd64_prepare_rex(int dst_reg, int src_reg,
int use_w, u8 *p_rex,
u8 *p_dst_low, u8 *p_src_low) {
u8 rex = 0x40;
if (use_w)
rex |= 0x08;
@@ -105,8 +107,8 @@ static inline int scc_mcode_amd64_prepare_rex(int dst_reg, int src_reg,
* @param mcode 机器码缓冲区
* @param width 宽度1=8位2=16位4=32位8=64位
*/
static inline void scc_mcode_amd64_emit_width_prefix(scc_mcode_t *mcode,
int width) {
SCC_MCODE_FUNC void scc_mcode_amd64_emit_width_prefix(scc_mcode_t *mcode,
int width) {
if (width == 2) {
scc_mcode_add_u8(mcode, 0x66);
}
@@ -121,7 +123,7 @@ static inline void scc_mcode_amd64_emit_width_prefix(scc_mcode_t *mcode,
* @param mcode 机器码缓冲区
* @param reg 寄存器编号
*/
static inline void scc_mcode_amd64_push_r64(scc_mcode_t *mcode, int reg) {
SCC_MCODE_FUNC void scc_mcode_amd64_push_r64(scc_mcode_t *mcode, int reg) {
if (reg < 8) {
scc_mcode_add_u8(mcode, 0x50 + reg);
} else {
@@ -136,7 +138,7 @@ static inline void scc_mcode_amd64_push_r64(scc_mcode_t *mcode, int reg) {
* @param mcode 机器码缓冲区
* @param reg 寄存器编号
*/
static inline void scc_mcode_amd64_pop_r64(scc_mcode_t *mcode, int reg) {
SCC_MCODE_FUNC void scc_mcode_amd64_pop_r64(scc_mcode_t *mcode, int reg) {
if (reg < 8) {
scc_mcode_add_u8(mcode, 0x58 + reg);
} else {
@@ -151,7 +153,7 @@ static inline void scc_mcode_amd64_pop_r64(scc_mcode_t *mcode, int reg) {
* @param mcode 机器码缓冲区
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_push_imm32(scc_mcode_t *mcode, u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_push_imm32(scc_mcode_t *mcode, u32 imm) {
scc_mcode_add_u8(mcode, 0x68);
scc_mcode_add_u32(mcode, imm);
}
@@ -167,8 +169,8 @@ static inline void scc_mcode_amd64_push_imm32(scc_mcode_t *mcode, u32 imm) {
* @param reg 目标寄存器
* @param imm 64 位立即数
*/
static inline void scc_mcode_amd64_mov_r64_imm64(scc_mcode_t *mcode, int reg,
u64 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_imm64(scc_mcode_t *mcode, int reg,
u64 imm) {
u8 rex = 0x48; // REX.W
if (reg >= 8) {
rex |= 0x01; // REX.B
@@ -186,8 +188,8 @@ static inline void scc_mcode_amd64_mov_r64_imm64(scc_mcode_t *mcode, int reg,
* @param reg 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_mov_r64_imm32(scc_mcode_t *mcode, int reg,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_imm32(scc_mcode_t *mcode, int reg,
u32 imm) {
u8 rex = 0x40; // REX.W=0
if (reg >= 8) {
rex |= 0x01; // REX.B
@@ -205,8 +207,8 @@ static inline void scc_mcode_amd64_mov_r64_imm32(scc_mcode_t *mcode, int reg,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48; // REX.W
if (src >= 8)
rex |= 0x04; // REX.R
@@ -225,8 +227,8 @@ static inline void scc_mcode_amd64_mov_r64_r64(scc_mcode_t *mcode, int dst,
* @param base 基址寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m64_r64(scc_mcode_t *mcode, int base,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m64_r64(scc_mcode_t *mcode, int base,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -251,8 +253,8 @@ static inline void scc_mcode_amd64_mov_m64_r64(scc_mcode_t *mcode, int base,
* @param dst 目标寄存器
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_mov_r64_m64(scc_mcode_t *mcode, int dst,
int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_m64(scc_mcode_t *mcode, int dst,
int base) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -278,9 +280,9 @@ static inline void scc_mcode_amd64_mov_r64_m64(scc_mcode_t *mcode, int dst,
* @param disp 32 位偏移
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m64_disp32_r64(scc_mcode_t *mcode,
int base, u32 disp,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m64_disp32_r64(scc_mcode_t *mcode,
int base, u32 disp,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -307,9 +309,9 @@ static inline void scc_mcode_amd64_mov_m64_disp32_r64(scc_mcode_t *mcode,
* @param base 基址寄存器
* @param disp 32 位偏移
*/
static inline void scc_mcode_amd64_mov_r64_m64_disp32(scc_mcode_t *mcode,
int dst, int base,
u32 disp) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_m64_disp32(scc_mcode_t *mcode,
int dst, int base,
u32 disp) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -328,6 +330,32 @@ static inline void scc_mcode_amd64_mov_r64_m64_disp32(scc_mcode_t *mcode,
scc_mcode_add_u32(mcode, disp);
}
/**
* @brief 加载 RIP 相对地址到 64 位寄存器 (lea r64, [rip+disp32])
*
* @param mcode 机器码缓冲区
* @param dst 目标寄存器 (0-15)
* @param disp 32 位相对偏移量 (有符号)
*/
SCC_MCODE_FUNC void scc_mcode_amd64_lea_r64_rip_rel32(scc_mcode_t *mcode,
int dst, u32 disp) {
// REX.W = 1, 无额外扩展位RIP 不是通用寄存器,不涉及 REX.B/R/X
u8 rex = 0x48;
if (dst >= 8) {
rex |= 0x04; // REX.R 位,因为 dst 放在 reg 字段
dst -= 8;
}
scc_mcode_add_u8(mcode, rex);
scc_mcode_add_u8(mcode, 0x8D); // LEA opcode
// ModRM: mod=00 (无位移), reg=dst, r/m=101 (RIP 相对寻址)
u8 modrm = 0x05 | ((dst & 7) << 3);
scc_mcode_add_u8(mcode, modrm);
// disp32 (有符号)
scc_mcode_add_u32(mcode, (u32)disp);
}
/**
* @brief 加载有效地址到 64 位寄存器 (lea r64, [base+disp32])
*
@@ -336,9 +364,9 @@ static inline void scc_mcode_amd64_mov_r64_m64_disp32(scc_mcode_t *mcode,
* @param base 基址寄存器
* @param disp 32 位偏移
*/
static inline void scc_mcode_amd64_lea_r64_m64_disp32(scc_mcode_t *mcode,
int dst, int base,
u32 disp) {
SCC_MCODE_FUNC void scc_mcode_amd64_lea_r64_m64_disp32(scc_mcode_t *mcode,
int dst, int base,
u32 disp) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -366,8 +394,8 @@ static inline void scc_mcode_amd64_lea_r64_m64_disp32(scc_mcode_t *mcode,
* @param dst 目标寄存器(低 32 位)
* @param src 源寄存器(低 32 位)
*/
static inline void scc_mcode_amd64_mov_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40; // REX.W=0
if (src >= 8)
rex |= 0x04;
@@ -386,8 +414,8 @@ static inline void scc_mcode_amd64_mov_r32_r32(scc_mcode_t *mcode, int dst,
* @param reg 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_mov_r32_imm32(scc_mcode_t *mcode, int reg,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r32_imm32(scc_mcode_t *mcode, int reg,
u32 imm) {
scc_mcode_amd64_mov_r64_imm32(mcode, reg, imm); // 与 64 位 imm32 版本相同
}
@@ -398,8 +426,8 @@ static inline void scc_mcode_amd64_mov_r32_imm32(scc_mcode_t *mcode, int reg,
* @param base 基址寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m32_r32(scc_mcode_t *mcode, int base,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m32_r32(scc_mcode_t *mcode, int base,
int src) {
u8 rex = 0x40; // REX.W=0
if (src >= 8)
rex |= 0x04;
@@ -424,8 +452,8 @@ static inline void scc_mcode_amd64_mov_m32_r32(scc_mcode_t *mcode, int base,
* @param dst 目标寄存器
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_mov_r32_m32(scc_mcode_t *mcode, int dst,
int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r32_m32(scc_mcode_t *mcode, int dst,
int base) {
u8 rex = 0x40; // REX.W=0
if (dst >= 8)
rex |= 0x04;
@@ -452,8 +480,8 @@ static inline void scc_mcode_amd64_mov_r32_m32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器(低 16 位)
* @param src 源寄存器(低 16 位)
*/
static inline void scc_mcode_amd64_mov_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40; // REX.W=0
if (src >= 8)
@@ -473,8 +501,8 @@ static inline void scc_mcode_amd64_mov_r16_r16(scc_mcode_t *mcode, int dst,
* @param reg 目标寄存器
* @param imm 16 位立即数
*/
static inline void scc_mcode_amd64_mov_r16_imm16(scc_mcode_t *mcode, int reg,
u16 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r16_imm16(scc_mcode_t *mcode, int reg,
u16 imm) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40; // REX.W=0
if (reg >= 8) {
@@ -493,8 +521,8 @@ static inline void scc_mcode_amd64_mov_r16_imm16(scc_mcode_t *mcode, int reg,
* @param base 基址寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m16_r16(scc_mcode_t *mcode, int base,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m16_r16(scc_mcode_t *mcode, int base,
int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -520,8 +548,8 @@ static inline void scc_mcode_amd64_mov_m16_r16(scc_mcode_t *mcode, int base,
* @param dst 目标寄存器
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_mov_r16_m16(scc_mcode_t *mcode, int dst,
int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r16_m16(scc_mcode_t *mcode, int dst,
int base) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (dst >= 8)
@@ -550,7 +578,7 @@ static inline void scc_mcode_amd64_mov_r16_m16(scc_mcode_t *mcode, int dst,
* @param reg 寄存器编号
* @return 是否需要 REX 前缀
*/
static inline int scc_mcode_amd64_is_byte_reg_needs_rex(int reg) {
SCC_MCODE_FUNC int scc_mcode_amd64_is_byte_reg_needs_rex(int reg) {
return (reg >= 4 && reg <= 7) || reg >= 8;
}
@@ -561,8 +589,8 @@ static inline int scc_mcode_amd64_is_byte_reg_needs_rex(int reg) {
* @param dst 目标寄存器(低 8 位)
* @param src 源寄存器(低 8 位)
*/
static inline void scc_mcode_amd64_mov_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) ||
scc_mcode_amd64_is_byte_reg_needs_rex(src);
@@ -585,8 +613,8 @@ static inline void scc_mcode_amd64_mov_r8_r8(scc_mcode_t *mcode, int dst,
* @param reg 目标寄存器
* @param imm 8 位立即数
*/
static inline void scc_mcode_amd64_mov_r8_imm8(scc_mcode_t *mcode, int reg,
u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r8_imm8(scc_mcode_t *mcode, int reg,
u8 imm) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(reg);
if (reg >= 8) {
@@ -607,8 +635,8 @@ static inline void scc_mcode_amd64_mov_r8_imm8(scc_mcode_t *mcode, int reg,
* @param base 基址寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m8_r8(scc_mcode_t *mcode, int base,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m8_r8(scc_mcode_t *mcode, int base,
int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src) ||
scc_mcode_amd64_is_byte_reg_needs_rex(base);
@@ -637,8 +665,8 @@ static inline void scc_mcode_amd64_mov_m8_r8(scc_mcode_t *mcode, int base,
* @param dst 目标寄存器
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_mov_r8_m8(scc_mcode_t *mcode, int dst,
int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r8_m8(scc_mcode_t *mcode, int dst,
int base) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) ||
scc_mcode_amd64_is_byte_reg_needs_rex(base);
@@ -669,8 +697,8 @@ static inline void scc_mcode_amd64_mov_r8_m8(scc_mcode_t *mcode, int dst,
* @param dst 64 位目标寄存器
* @param src 8 位源寄存器
*/
static inline void scc_mcode_amd64_movsx_r64_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48; // REX.W
if (dst >= 8)
rex |= 0x04;
@@ -690,8 +718,8 @@ static inline void scc_mcode_amd64_movsx_r64_r8(scc_mcode_t *mcode, int dst,
* @param dst 64 位目标寄存器
* @param src 16 位源寄存器
*/
static inline void scc_mcode_amd64_movsx_r64_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_r16(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -711,8 +739,8 @@ static inline void scc_mcode_amd64_movsx_r64_r16(scc_mcode_t *mcode, int dst,
* @param dst 64 位目标寄存器
* @param src 32 位源寄存器
*/
static inline void scc_mcode_amd64_movsx_r64_r32(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_r32(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -731,8 +759,8 @@ static inline void scc_mcode_amd64_movsx_r64_r32(scc_mcode_t *mcode, int dst,
* @param dst 64 位目标寄存器
* @param src 8 位源寄存器
*/
static inline void scc_mcode_amd64_movzx_r64_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_movzx_r64_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -752,8 +780,8 @@ static inline void scc_mcode_amd64_movzx_r64_r8(scc_mcode_t *mcode, int dst,
* @param dst 64 位目标寄存器
* @param src 16 位源寄存器
*/
static inline void scc_mcode_amd64_movzx_r64_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_movzx_r64_r16(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -777,8 +805,8 @@ static inline void scc_mcode_amd64_movzx_r64_r16(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_add_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -797,8 +825,8 @@ static inline void scc_mcode_amd64_add_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_add_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -816,8 +844,8 @@ static inline void scc_mcode_amd64_add_r64_imm32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_sub_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -836,8 +864,8 @@ static inline void scc_mcode_amd64_sub_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_sub_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -854,7 +882,7 @@ static inline void scc_mcode_amd64_sub_r64_imm32(scc_mcode_t *mcode, int dst,
* @param mcode 机器码缓冲区
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_sub_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
scc_mcode_amd64_sub_r64_imm32(mcode, SCC_AMD64_RSP, imm);
}
@@ -864,7 +892,7 @@ static inline void scc_mcode_amd64_sub_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
* @param mcode 机器码缓冲区
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_add_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
scc_mcode_amd64_add_r64_imm32(mcode, SCC_AMD64_RSP, imm);
}
@@ -875,8 +903,8 @@ static inline void scc_mcode_amd64_add_rsp_imm32(scc_mcode_t *mcode, u32 imm) {
* @param dst 左操作数寄存器
* @param src 右操作数寄存器
*/
static inline void scc_mcode_amd64_cmp_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_cmp_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -895,8 +923,8 @@ static inline void scc_mcode_amd64_cmp_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_cmp_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_cmp_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -914,8 +942,8 @@ static inline void scc_mcode_amd64_cmp_r64_imm32(scc_mcode_t *mcode, int dst,
* @param dst 目标/左操作数寄存器
* @param src 右操作数寄存器
*/
static inline void scc_mcode_amd64_imul_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04; // dst in reg field
@@ -936,9 +964,9 @@ static inline void scc_mcode_amd64_imul_r64_r64(scc_mcode_t *mcode, int dst,
* @param src 源寄存器或内存(此处为寄存器版本)
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_imul_r64_r64_imm32(scc_mcode_t *mcode,
int dst, int src,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r64_r64_imm32(scc_mcode_t *mcode,
int dst, int src,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -960,8 +988,9 @@ static inline void scc_mcode_amd64_imul_r64_r64_imm32(scc_mcode_t *mcode,
* @param src 源寄存器或内存(此处为寄存器版本)
* @param imm 8 位立即数
*/
static inline void scc_mcode_amd64_imul_r64_r64_imm8(scc_mcode_t *mcode,
int dst, int src, u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r64_r64_imm8(scc_mcode_t *mcode,
int dst, int src,
u8 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -983,8 +1012,8 @@ static inline void scc_mcode_amd64_imul_r64_r64_imm8(scc_mcode_t *mcode,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_add_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40; // REX.W=0
if (src >= 8)
rex |= 0x04;
@@ -1003,8 +1032,8 @@ static inline void scc_mcode_amd64_add_r32_r32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_add_r32_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r32_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x40;
if (dst >= 8)
rex |= 0x01;
@@ -1022,8 +1051,8 @@ static inline void scc_mcode_amd64_add_r32_imm32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_sub_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x04;
@@ -1042,8 +1071,8 @@ static inline void scc_mcode_amd64_sub_r32_r32(scc_mcode_t *mcode, int dst,
* @param dst 左操作数寄存器
* @param src 右操作数寄存器
*/
static inline void scc_mcode_amd64_cmp_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_cmp_r32_r32(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x04;
@@ -1064,8 +1093,8 @@ static inline void scc_mcode_amd64_cmp_r32_r32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_add_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1085,8 +1114,8 @@ static inline void scc_mcode_amd64_add_r16_r16(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 16 位立即数
*/
static inline void scc_mcode_amd64_add_r16_imm16(scc_mcode_t *mcode, int dst,
u16 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r16_imm16(scc_mcode_t *mcode, int dst,
u16 imm) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (dst >= 8)
@@ -1105,8 +1134,8 @@ static inline void scc_mcode_amd64_add_r16_imm16(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_sub_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1126,8 +1155,8 @@ static inline void scc_mcode_amd64_sub_r16_r16(scc_mcode_t *mcode, int dst,
* @param dst 左操作数寄存器
* @param src 右操作数寄存器
*/
static inline void scc_mcode_amd64_cmp_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_cmp_r16_r16(scc_mcode_t *mcode, int dst,
int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1149,8 +1178,8 @@ static inline void scc_mcode_amd64_cmp_r16_r16(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_add_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) ||
scc_mcode_amd64_is_byte_reg_needs_rex(src);
@@ -1173,8 +1202,8 @@ static inline void scc_mcode_amd64_add_r8_r8(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 8 位立即数
*/
static inline void scc_mcode_amd64_add_r8_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_add_r8_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst);
if (dst >= 8) {
@@ -1197,8 +1226,8 @@ static inline void scc_mcode_amd64_add_r8_imm8(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_sub_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_sub_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) ||
scc_mcode_amd64_is_byte_reg_needs_rex(src);
@@ -1221,8 +1250,8 @@ static inline void scc_mcode_amd64_sub_r8_r8(scc_mcode_t *mcode, int dst,
* @param dst 左操作数寄存器
* @param src 右操作数寄存器
*/
static inline void scc_mcode_amd64_cmp_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_cmp_r8_r8(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst) ||
scc_mcode_amd64_is_byte_reg_needs_rex(src);
@@ -1248,7 +1277,7 @@ static inline void scc_mcode_amd64_cmp_r8_r8(scc_mcode_t *mcode, int dst,
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mul_r64(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mul_r64(scc_mcode_t *mcode, int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x01;
@@ -1264,7 +1293,7 @@ static inline void scc_mcode_amd64_mul_r64(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mul_r32(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mul_r32(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x01;
@@ -1280,7 +1309,7 @@ static inline void scc_mcode_amd64_mul_r32(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mul_r16(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mul_r16(scc_mcode_t *mcode, int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1297,7 +1326,7 @@ static inline void scc_mcode_amd64_mul_r16(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mul_r8(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mul_r8(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src);
if (src >= 8)
@@ -1318,7 +1347,7 @@ static inline void scc_mcode_amd64_mul_r8(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_imul_r64_1op(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r64_1op(scc_mcode_t *mcode, int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x01;
@@ -1334,7 +1363,7 @@ static inline void scc_mcode_amd64_imul_r64_1op(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_imul_r32_1op(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r32_1op(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x01;
@@ -1350,7 +1379,7 @@ static inline void scc_mcode_amd64_imul_r32_1op(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_imul_r16_1op(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r16_1op(scc_mcode_t *mcode, int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1367,7 +1396,7 @@ static inline void scc_mcode_amd64_imul_r16_1op(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_imul_r8_1op(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_imul_r8_1op(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src);
if (src >= 8)
@@ -1388,7 +1417,7 @@ static inline void scc_mcode_amd64_imul_r8_1op(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_div_r64(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_div_r64(scc_mcode_t *mcode, int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x01;
@@ -1404,7 +1433,7 @@ static inline void scc_mcode_amd64_div_r64(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_div_r32(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_div_r32(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x01;
@@ -1420,7 +1449,7 @@ static inline void scc_mcode_amd64_div_r32(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_div_r16(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_div_r16(scc_mcode_t *mcode, int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1437,7 +1466,7 @@ static inline void scc_mcode_amd64_div_r16(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_div_r8(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_div_r8(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src);
if (src >= 8)
@@ -1458,7 +1487,7 @@ static inline void scc_mcode_amd64_div_r8(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_idiv_r64(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_idiv_r64(scc_mcode_t *mcode, int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x01;
@@ -1474,7 +1503,7 @@ static inline void scc_mcode_amd64_idiv_r64(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_idiv_r32(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_idiv_r32(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
if (src >= 8)
rex |= 0x01;
@@ -1490,7 +1519,7 @@ static inline void scc_mcode_amd64_idiv_r32(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_idiv_r16(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_idiv_r16(scc_mcode_t *mcode, int src) {
scc_mcode_amd64_emit_width_prefix(mcode, 2);
u8 rex = 0x40;
if (src >= 8)
@@ -1507,7 +1536,7 @@ static inline void scc_mcode_amd64_idiv_r16(scc_mcode_t *mcode, int src) {
* @param mcode 机器码缓冲区
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_idiv_r8(scc_mcode_t *mcode, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_idiv_r8(scc_mcode_t *mcode, int src) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(src);
if (src >= 8)
@@ -1531,8 +1560,8 @@ static inline void scc_mcode_amd64_idiv_r8(scc_mcode_t *mcode, int src) {
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_and_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_and_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -1551,8 +1580,8 @@ static inline void scc_mcode_amd64_and_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_and_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_and_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1570,8 +1599,8 @@ static inline void scc_mcode_amd64_and_r64_imm32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_or_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_or_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -1590,8 +1619,8 @@ static inline void scc_mcode_amd64_or_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_or_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_or_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1609,8 +1638,8 @@ static inline void scc_mcode_amd64_or_r64_imm32(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_xor_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_xor_r64_r64(scc_mcode_t *mcode, int dst,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -1629,8 +1658,8 @@ static inline void scc_mcode_amd64_xor_r64_r64(scc_mcode_t *mcode, int dst,
* @param dst 目标寄存器
* @param imm 32 位立即数
*/
static inline void scc_mcode_amd64_xor_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_xor_r64_imm32(scc_mcode_t *mcode, int dst,
u32 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1651,7 +1680,7 @@ static inline void scc_mcode_amd64_xor_r64_imm32(scc_mcode_t *mcode, int dst,
* @param mcode 机器码缓冲区
* @param dst 目标寄存器
*/
static inline void scc_mcode_amd64_shl_r64_1(scc_mcode_t *mcode, int dst) {
SCC_MCODE_FUNC void scc_mcode_amd64_shl_r64_1(scc_mcode_t *mcode, int dst) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1668,8 +1697,8 @@ static inline void scc_mcode_amd64_shl_r64_1(scc_mcode_t *mcode, int dst) {
* @param dst 目标寄存器
* @param imm 移位次数
*/
static inline void scc_mcode_amd64_shl_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_shl_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1686,7 +1715,7 @@ static inline void scc_mcode_amd64_shl_r64_imm8(scc_mcode_t *mcode, int dst,
* @param mcode 机器码缓冲区
* @param dst 目标寄存器
*/
static inline void scc_mcode_amd64_shr_r64_1(scc_mcode_t *mcode, int dst) {
SCC_MCODE_FUNC void scc_mcode_amd64_shr_r64_1(scc_mcode_t *mcode, int dst) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1703,8 +1732,8 @@ static inline void scc_mcode_amd64_shr_r64_1(scc_mcode_t *mcode, int dst) {
* @param dst 目标寄存器
* @param imm 移位次数
*/
static inline void scc_mcode_amd64_shr_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_shr_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1721,7 +1750,7 @@ static inline void scc_mcode_amd64_shr_r64_imm8(scc_mcode_t *mcode, int dst,
* @param mcode 机器码缓冲区
* @param dst 目标寄存器
*/
static inline void scc_mcode_amd64_sar_r64_1(scc_mcode_t *mcode, int dst) {
SCC_MCODE_FUNC void scc_mcode_amd64_sar_r64_1(scc_mcode_t *mcode, int dst) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1738,8 +1767,8 @@ static inline void scc_mcode_amd64_sar_r64_1(scc_mcode_t *mcode, int dst) {
* @param dst 目标寄存器
* @param imm 移位次数
*/
static inline void scc_mcode_amd64_sar_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
SCC_MCODE_FUNC void scc_mcode_amd64_sar_r64_imm8(scc_mcode_t *mcode, int dst,
u8 imm) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x01;
@@ -1759,8 +1788,8 @@ static inline void scc_mcode_amd64_sar_r64_imm8(scc_mcode_t *mcode, int dst,
* @param cond 条件码0-15
* @param reg 目标 8 位寄存器
*/
static inline void scc_mcode_amd64_setcc_r8(scc_mcode_t *mcode, int cond,
int reg) {
SCC_MCODE_FUNC void scc_mcode_amd64_setcc_r8(scc_mcode_t *mcode, int cond,
int reg) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(reg);
if (reg >= 8) {
@@ -1783,8 +1812,8 @@ static inline void scc_mcode_amd64_setcc_r8(scc_mcode_t *mcode, int cond,
* @param cond 条件码
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_setcc_m8(scc_mcode_t *mcode, int cond,
int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_setcc_m8(scc_mcode_t *mcode, int cond,
int base) {
u8 rex = 0x40;
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(base);
if (base >= 8) {
@@ -1814,7 +1843,7 @@ static inline void scc_mcode_amd64_setcc_m8(scc_mcode_t *mcode, int cond,
* @param mcode 机器码缓冲区
* @param rel32 32 位相对偏移
*/
static inline void scc_mcode_amd64_jmp_rel32(scc_mcode_t *mcode, u32 rel32) {
SCC_MCODE_FUNC void scc_mcode_amd64_jmp_rel32(scc_mcode_t *mcode, u32 rel32) {
scc_mcode_add_u8(mcode, 0xE9);
scc_mcode_add_u32(mcode, rel32);
}
@@ -1826,8 +1855,8 @@ static inline void scc_mcode_amd64_jmp_rel32(scc_mcode_t *mcode, u32 rel32) {
* @param cond 条件码
* @param rel32 32 位相对偏移
*/
static inline void scc_mcode_amd64_jcc_rel32(scc_mcode_t *mcode, int cond,
u32 rel32) {
SCC_MCODE_FUNC void scc_mcode_amd64_jcc_rel32(scc_mcode_t *mcode, int cond,
u32 rel32) {
scc_mcode_add_u8(mcode, 0x0F);
scc_mcode_add_u8(mcode, 0x80 + cond);
scc_mcode_add_u32(mcode, rel32);
@@ -1839,7 +1868,7 @@ static inline void scc_mcode_amd64_jcc_rel32(scc_mcode_t *mcode, int cond,
* @param mcode 机器码缓冲区
* @param rel32 32 位相对偏移
*/
static inline void scc_mcode_amd64_call_rel32(scc_mcode_t *mcode, u32 rel32) {
SCC_MCODE_FUNC void scc_mcode_amd64_call_rel32(scc_mcode_t *mcode, u32 rel32) {
scc_mcode_add_u8(mcode, 0xE8);
scc_mcode_add_u32(mcode, rel32);
}
@@ -1850,7 +1879,7 @@ static inline void scc_mcode_amd64_call_rel32(scc_mcode_t *mcode, u32 rel32) {
* @param mcode 机器码缓冲区
* @param reg 目标寄存器(存储跳转地址)
*/
static inline void scc_mcode_amd64_jmp_r64(scc_mcode_t *mcode, int reg) {
SCC_MCODE_FUNC void scc_mcode_amd64_jmp_r64(scc_mcode_t *mcode, int reg) {
u8 rex = 0x40;
if (reg >= 8)
rex |= 0x01;
@@ -1866,7 +1895,7 @@ static inline void scc_mcode_amd64_jmp_r64(scc_mcode_t *mcode, int reg) {
* @param mcode 机器码缓冲区
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_jmp_m64(scc_mcode_t *mcode, int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_jmp_m64(scc_mcode_t *mcode, int base) {
u8 rex = 0x48;
if (base >= 8)
rex |= 0x01;
@@ -1888,7 +1917,7 @@ static inline void scc_mcode_amd64_jmp_m64(scc_mcode_t *mcode, int base) {
* @param mcode 机器码缓冲区
* @param reg 目标寄存器
*/
static inline void scc_mcode_amd64_call_r64(scc_mcode_t *mcode, int reg) {
SCC_MCODE_FUNC void scc_mcode_amd64_call_r64(scc_mcode_t *mcode, int reg) {
u8 rex = 0x40;
if (reg >= 8)
rex |= 0x01;
@@ -1904,7 +1933,7 @@ static inline void scc_mcode_amd64_call_r64(scc_mcode_t *mcode, int reg) {
* @param mcode 机器码缓冲区
* @param base 基址寄存器
*/
static inline void scc_mcode_amd64_call_m64(scc_mcode_t *mcode, int base) {
SCC_MCODE_FUNC void scc_mcode_amd64_call_m64(scc_mcode_t *mcode, int base) {
u8 rex = 0x48;
if (base >= 8)
rex |= 0x01;
@@ -1925,7 +1954,7 @@ static inline void scc_mcode_amd64_call_m64(scc_mcode_t *mcode, int base) {
*
* @param mcode 机器码缓冲区
*/
static inline void scc_mcode_amd64_ret(scc_mcode_t *mcode) {
SCC_MCODE_FUNC void scc_mcode_amd64_ret(scc_mcode_t *mcode) {
scc_mcode_add_u8(mcode, 0xC3);
}
@@ -1936,7 +1965,7 @@ static inline void scc_mcode_amd64_ret(scc_mcode_t *mcode) {
*
* @param mcode 机器码缓冲区
*/
static inline void scc_mcode_amd64_syscall(scc_mcode_t *mcode) {
SCC_MCODE_FUNC void scc_mcode_amd64_syscall(scc_mcode_t *mcode) {
scc_mcode_add_u8(mcode, 0x0F);
scc_mcode_add_u8(mcode, 0x05);
}
@@ -1946,10 +1975,10 @@ static inline void scc_mcode_amd64_syscall(scc_mcode_t *mcode) {
// 辅助函数:根据 base, index, scale, disp 生成 ModRM 和 SIB 字节并写入
// 返回需要写入 disp 的字节数0,1,4调用者需写入 disp
static inline int scc_mcode_amd64_emit_sib_address(scc_mcode_t *mcode, int base,
int index, int scale,
u32 disp, int has_disp,
int disp8) {
SCC_MCODE_FUNC int scc_mcode_amd64_emit_sib_address(scc_mcode_t *mcode,
int base, int index,
int scale, u32 disp,
int has_disp, int disp8) {
// scale 编码: 0=1, 1=2, 2=4, 3=8
u8 scale_code = 0;
switch (scale) {
@@ -2013,7 +2042,7 @@ static inline int scc_mcode_amd64_emit_sib_address(scc_mcode_t *mcode, int base,
// * @param disp 位移量
// * @param disp_size 位移大小0=无位移1=8位4=32位
// */
// static inline void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int
// SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int
// dst,
// int base, int index, int
// scale, u32 disp, int
@@ -2049,9 +2078,9 @@ static inline int scc_mcode_amd64_emit_sib_address(scc_mcode_t *mcode, int base,
* @param scale 比例因子1,2,4,8
* @param disp 位移量
*/
static inline void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int dst,
int base, int index,
int scale, u32 disp) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int dst,
int base, int index,
int scale, u32 disp) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;
@@ -2133,9 +2162,10 @@ static inline void scc_mcode_amd64_mov_r64_m64_sib(scc_mcode_t *mcode, int dst,
* @param disp 位移量
* @param src 源寄存器
*/
static inline void scc_mcode_amd64_mov_m64_sib_r64(scc_mcode_t *mcode, int base,
int index, int scale,
u32 disp, int src) {
SCC_MCODE_FUNC void scc_mcode_amd64_mov_m64_sib_r64(scc_mcode_t *mcode,
int base, int index,
int scale, u32 disp,
int src) {
u8 rex = 0x48;
if (src >= 8)
rex |= 0x04;
@@ -2214,9 +2244,9 @@ static inline void scc_mcode_amd64_mov_m64_sib_r64(scc_mcode_t *mcode, int base,
* @param scale 比例因子
* @param disp 位移量
*/
static inline void scc_mcode_amd64_lea_r64_m64_sib(scc_mcode_t *mcode, int dst,
int base, int index,
int scale, u32 disp) {
SCC_MCODE_FUNC void scc_mcode_amd64_lea_r64_m64_sib(scc_mcode_t *mcode, int dst,
int base, int index,
int scale, u32 disp) {
u8 rex = 0x48;
if (dst >= 8)
rex |= 0x04;

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

@@ -5,6 +5,7 @@
typedef struct {
scc_hashtable_t str2libsym;
scc_pe_idata_lib_vec_t idata_libs;
const char *find_path;
} pe_idata_lib_ctx_t;
static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
@@ -15,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);
@@ -57,14 +58,15 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
}
}
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx) {
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
// Got .dll.def
scc_hashtable_init(&ctx->str2libsym,
(scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp);
scc_vec_init(ctx->idata_libs);
load_from_def(ctx, __FILE__ "/../../.dll_def", "ucrtbase.dll");
ctx->find_path = find_path;
load_from_def(ctx, ctx->find_path, "ucrtbase.dll");
}
static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) {
@@ -149,7 +151,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
}
pe_idata_lib_ctx_t idata_lib_ctx;
pe_idata_lib_init(&idata_lib_ctx);
pe_idata_lib_init(&idata_lib_ctx, __FILE__ "/../../.dll_def");
scc_vec_foreach(symtab, i) {
sccf_sym_t *sym = &scc_vec_at(symtab, i);
if (sym->sccf_sym_type == SCCF_SYM_TYPE_EXTERN) {
@@ -218,7 +220,6 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
TODO();
}
Assert(reloc->sect_type == SCCF_SECT_CODE);
rva -= code_range.virual_address + reloc->offset + reloc->addend;
Assert(code_data != null);
// FIXME 需要确保宿主机与目标机器大小端一致

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

@@ -8,7 +8,7 @@
#define UNALIGNED_ACCESS_ALLOWED 0
#endif
void *scc_memcpy(void *dest, const void *restrict src, usize n) {
void *scc_memcpy(void *dest, const void *src, usize n) {
char *d = (char *)dest;
const char *s = (const char *)src;

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

1
src/target.c Normal file
View File

@@ -0,0 +1 @@

View File

@@ -1,6 +0,0 @@
#include "scc_stdio.h"
int main(void) {
puts("hello world");
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;
}

12
tests/simple/14_pointer.c Normal file
View File

@@ -0,0 +1,12 @@
void exchange(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
int main(void) {
int a = 1, b = 3;
exchange(&a, &b);
return a - b;
}

View File

@@ -1,4 +1,7 @@
[return_val_cases]
# windows powershell: echo $LASTEXITCODE
# nushell: echo $env.LAST_EXIT_CODE
# bash: echo $?
"./01_return.c" = 65536
"./02_decl_expr.c" = 1
"./03_decl_init.c" = 11
@@ -10,4 +13,7 @@
"./09_for.c" = 10
"./10_main.c" = 3
"./11_recursive.c" = 120
"./12_logic.c" = 10
"./13_array.c" = 1198
"./14_pointer.c" = 2
[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