Compare commits
3 Commits
4ddad7b456
...
27d86d5685
| Author | SHA1 | Date | |
|---|---|---|---|
| 27d86d5685 | |||
| ca187c78f1 | |||
| 78e7c800ba |
4
Doxyfile
4
Doxyfile
@@ -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
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
49
libs/ir/include/ir_module.h
Normal file
49
libs/ir/include/ir_module.h
Normal 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__ */
|
||||
@@ -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;
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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), ¶m_node);
|
||||
scc_ir_value_ref_t param_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), ¶m_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);
|
||||
|
||||
@@ -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
137
libs/ir/src/ir_module.c
Normal 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];
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
27
libs/ir2mcode/include/frame_manager.h
Normal file
27
libs/ir2mcode/include/frame_manager.h
Normal 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__ */
|
||||
@@ -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))
|
||||
|
||||
0
libs/ir2mcode/src/frame_manager.c
Normal file
0
libs/ir2mcode/src/frame_manager.c
Normal 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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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); \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.");
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@ static inline scc_lexer_tok_t scc_pproc_tok_copy(scc_pproc_expand_t *ctx,
|
||||
static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_vec_t *arg_tokens) {
|
||||
// WRITE BY AI
|
||||
scc_cstring_t str = scc_cstring_create();
|
||||
scc_cstring_append_ch(&str, '\"'); // 左引号
|
||||
scc_str_t str = scc_str_empty();
|
||||
scc_str_append_ch(&str, '\"'); // 左引号
|
||||
|
||||
int need_space = 0; // 是否需要插入空格
|
||||
scc_lexer_tok_t *tok = null;
|
||||
@@ -32,7 +32,7 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
|
||||
// 需要空格且当前不是第一个有效token,插入一个空格
|
||||
if (need_space && i > 0) {
|
||||
scc_cstring_append_ch(&str, ' ');
|
||||
scc_str_append_ch(&str, ' ');
|
||||
}
|
||||
|
||||
// 对字符串/字符常量内的 " 和 \ 进行转义
|
||||
@@ -41,10 +41,10 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
// 注意:lex包含两端的引号,需要跳过首尾,转义内部字符
|
||||
// 简化:暂不处理内部转义,直接追加
|
||||
}
|
||||
scc_cstring_append(&str, &tok->lexeme);
|
||||
scc_str_append(&str, &tok->lexeme);
|
||||
need_space = 0;
|
||||
}
|
||||
scc_cstring_append_ch(&str, '\"'); // 右引号
|
||||
scc_str_append_ch(&str, '\"'); // 右引号
|
||||
|
||||
scc_lexer_tok_t result;
|
||||
result.type = SCC_TOK_STRING_LITERAL;
|
||||
@@ -60,19 +60,19 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx,
|
||||
const scc_lexer_tok_t *left,
|
||||
const scc_lexer_tok_t *right) {
|
||||
scc_cstring_t new_lex = scc_cstring_from_cstr("");
|
||||
scc_str_t new_lex = scc_str_from_cstr("");
|
||||
if (left != null) {
|
||||
scc_cstring_append(&new_lex, &left->lexeme);
|
||||
scc_str_append(&new_lex, &left->lexeme);
|
||||
}
|
||||
if (right != null) {
|
||||
scc_cstring_append(&new_lex, &right->lexeme);
|
||||
scc_str_append(&new_lex, &right->lexeme);
|
||||
}
|
||||
|
||||
scc_lexer_t lexer;
|
||||
scc_sstream_t sstream;
|
||||
// new_lex 所有权转移
|
||||
scc_sstream_init_by_buffer(&sstream, scc_cstring_as_cstr(&new_lex),
|
||||
scc_cstring_len(&new_lex), true, 8);
|
||||
scc_sstream_init_by_buffer(&sstream, scc_str_as_cstr(&new_lex),
|
||||
scc_str_len(&new_lex), true, 8);
|
||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
|
||||
scc_lexer_tok_ring_t *ring = scc_lexer_to_ring(&lexer, 8, true);
|
||||
|
||||
@@ -269,7 +269,7 @@ expand_arguments(scc_pproc_macro_extened_params_t *expanded_params,
|
||||
scc_vec_init(expanded_param);
|
||||
scc_vec_foreach(splite_param, j) {
|
||||
scc_lexer_tok_t tok = scc_vec_at(splite_param, j);
|
||||
tok.lexeme = scc_cstring_copy(&tok.lexeme);
|
||||
tok.lexeme = scc_str_copy(&tok.lexeme);
|
||||
scc_vec_push(expanded_param, tok);
|
||||
}
|
||||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(&expanded_param);
|
||||
@@ -353,8 +353,8 @@ RETURN:
|
||||
static int find_params(const scc_lexer_tok_t *tok,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
scc_vec_foreach(macro->params, j) {
|
||||
if (scc_cstring_cmp(&(tok->lexeme),
|
||||
&(scc_vec_at(macro->params, j).lexeme)) == 0) {
|
||||
if (scc_str_equal(&(tok->lexeme),
|
||||
&(scc_vec_at(macro->params, j).lexeme)) == 0) {
|
||||
return j;
|
||||
}
|
||||
}
|
||||
@@ -437,8 +437,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
scc_lexer_tok_t tok =
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||||
scc_str_drop(&tok.lexeme);
|
||||
tok.lexeme = scc_str_from_cstr(" ");
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
continue;
|
||||
}
|
||||
@@ -449,8 +449,8 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
int right_idx = got_right_non_blank(i, ¯o->replaces);
|
||||
if (right_idx >= (int)macro->replaces.size) {
|
||||
LOG_WARN("generate empty stringify");
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
tok.lexeme = scc_cstring_from_cstr("");
|
||||
scc_str_drop(&tok.lexeme);
|
||||
tok.lexeme = scc_str_from_cstr("");
|
||||
scc_vec_push(tok_buffer, tok);
|
||||
break;
|
||||
}
|
||||
@@ -491,7 +491,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
scc_vec_size(right_vec) ? &scc_vec_at(right_vec, 0) : null;
|
||||
|
||||
// GNU ## extention
|
||||
if (scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
|
||||
if (scc_strcmp(scc_str_as_cstr(&(right_tok->lexeme)),
|
||||
"__VA_ARGS__") == 0) {
|
||||
if (scc_vec_size(right_vec) == 0) {
|
||||
concact(ctx, &tok_buffer, right, true);
|
||||
@@ -550,8 +550,8 @@ static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
||||
scc_pproc_tok_copy(ctx, &scc_vec_at(macro->replaces, i));
|
||||
if (tok.type == SCC_TOK_BLANK) {
|
||||
// FIXME using function to warpper it
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
tok.lexeme = scc_cstring_from_cstr(" ");
|
||||
scc_str_drop(&tok.lexeme);
|
||||
tok.lexeme = scc_str_from_cstr(" ");
|
||||
} else if (tok.type == SCC_TOK_SHARP_SHARP) {
|
||||
// ## contact
|
||||
scc_lexer_tok_drop(&tok);
|
||||
@@ -635,7 +635,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||
}
|
||||
|
||||
if (expand_ctx->need_parse_defined &&
|
||||
scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) {
|
||||
scc_strcmp(scc_str_as_cstr(&tok.lexeme), "defined") == 0) {
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
if (parse_defined(expand_ctx, &pos)) {
|
||||
@@ -679,19 +679,19 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||
}
|
||||
// FIXME 这可能不符合c语义
|
||||
case SCC_PP_MACRO_BUILTIN__FILE__:
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
scc_cstring_append_ch(&tok.lexeme, '"');
|
||||
scc_cstring_append_cstr(&tok.lexeme, tok.loc.name,
|
||||
scc_strlen(tok.loc.name));
|
||||
scc_cstring_append_ch(&tok.lexeme, '"');
|
||||
scc_str_drop(&tok.lexeme);
|
||||
scc_str_append_ch(&tok.lexeme, '"');
|
||||
scc_str_append_cstr(&tok.lexeme, tok.loc.name,
|
||||
scc_strlen(tok.loc.name));
|
||||
scc_str_append_ch(&tok.lexeme, '"');
|
||||
tok.type = SCC_TOK_STRING_LITERAL;
|
||||
scc_vec_push(expand_ctx->output, tok);
|
||||
break;
|
||||
case SCC_PP_MACRO_BUILTIN__LINE__:
|
||||
scc_cstring_free(&tok.lexeme);
|
||||
scc_str_drop(&tok.lexeme);
|
||||
char *buff = scc_malloc(32);
|
||||
scc_snprintf(buff, 32, "%zu", tok.loc.line);
|
||||
tok.lexeme = scc_cstring_from_cstr(buff);
|
||||
tok.lexeme = scc_str_from_cstr(buff);
|
||||
scc_free(buff);
|
||||
tok.type = SCC_TOK_INT_LITERAL;
|
||||
scc_vec_push(expand_ctx->output, tok);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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(¯o->name);
|
||||
scc_str_drop(¯o->name);
|
||||
|
||||
scc_free(macro);
|
||||
}
|
||||
|
||||
// 添加对象宏
|
||||
cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros,
|
||||
const scc_cstring_t *name,
|
||||
const scc_str_t *name,
|
||||
const scc_lexer_tok_vec_t *replacement) {
|
||||
if (!macros || !name || !replacement)
|
||||
return false;
|
||||
@@ -56,7 +56,7 @@ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros,
|
||||
scc_pproc_macro_t *existing =
|
||||
scc_hashtable_get(¯os->table, ¯o->name);
|
||||
if (existing) {
|
||||
LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name));
|
||||
LOG_WARN("Redefining macro: %s", scc_str_as_cstr(¯o->name));
|
||||
scc_pproc_macro_drop(existing);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ cbool scc_pproc_add_object_macro(scc_pproc_macro_table_t *macros,
|
||||
|
||||
// 添加函数宏
|
||||
cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros,
|
||||
const scc_cstring_t *name,
|
||||
const scc_str_t *name,
|
||||
const scc_lexer_tok_vec_t *params,
|
||||
const scc_lexer_tok_vec_t *replacement) {
|
||||
if (!macros || !name || !params || !replacement)
|
||||
@@ -84,7 +84,7 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros,
|
||||
scc_pproc_macro_t *existing =
|
||||
scc_hashtable_get(¯os->table, ¯o->name);
|
||||
if (existing) {
|
||||
LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name));
|
||||
LOG_WARN("Redefining macro: %s", scc_str_as_cstr(¯o->name));
|
||||
scc_pproc_macro_drop(existing);
|
||||
}
|
||||
|
||||
@@ -96,10 +96,10 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros,
|
||||
|
||||
scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp,
|
||||
scc_pproc_macro_t *macro) {
|
||||
Assert(pp != null && macro != null && scc_cstring_len(¯o->name) != 0);
|
||||
Assert(pp != null && macro != null && scc_str_len(¯o->name) != 0);
|
||||
scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, ¯o->name, macro);
|
||||
if (old && old != macro) {
|
||||
LOG_WARN("same macro name `%s`", scc_cstring_as_cstr(¯o->name));
|
||||
LOG_WARN("same macro name `%s`", scc_str_as_cstr(¯o->name));
|
||||
scc_pproc_macro_drop(old);
|
||||
}
|
||||
return macro;
|
||||
@@ -107,13 +107,13 @@ scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp,
|
||||
|
||||
// 查找宏定义
|
||||
scc_pproc_macro_t *scc_pproc_macro_table_get(scc_pproc_macro_table_t *pp,
|
||||
const scc_cstring_t *name) {
|
||||
const scc_str_t *name) {
|
||||
return scc_hashtable_get(&pp->table, name);
|
||||
}
|
||||
|
||||
// 从预处理器中删除宏
|
||||
cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp,
|
||||
const scc_cstring_t *name) {
|
||||
const scc_str_t *name) {
|
||||
if (!pp || !name)
|
||||
return false;
|
||||
|
||||
@@ -127,18 +127,18 @@ cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp,
|
||||
}
|
||||
|
||||
static u32 hash_func(const void *key) {
|
||||
const scc_cstring_t *string = (const scc_cstring_t *)key;
|
||||
return scc_strhash32(scc_cstring_as_cstr(string));
|
||||
const scc_str_t *string = (const scc_str_t *)key;
|
||||
return scc_strhash32(scc_str_as_cstr(string));
|
||||
}
|
||||
|
||||
static int hash_cmp(const void *key1, const void *key2) {
|
||||
const scc_cstring_t *str1 = (const scc_cstring_t *)key1;
|
||||
const scc_cstring_t *str2 = (const scc_cstring_t *)key2;
|
||||
const scc_str_t *str1 = (const scc_str_t *)key1;
|
||||
const scc_str_t *str2 = (const scc_str_t *)key2;
|
||||
|
||||
if (str1->size != str2->size) {
|
||||
return str1->size - str2->size;
|
||||
}
|
||||
return scc_strcmp(scc_cstring_as_cstr(str1), scc_cstring_as_cstr(str2));
|
||||
return scc_strcmp(scc_str_as_cstr(str1), scc_str_as_cstr(str2));
|
||||
}
|
||||
|
||||
void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 需要确保宿主机与目标机器大小端一致
|
||||
|
||||
99
libs/tree_dump/include/scc_tree_dump.h
Normal file
99
libs/tree_dump/include/scc_tree_dump.h
Normal 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
|
||||
@@ -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__ */
|
||||
126
libs/tree_dump/src/scc_tree_dump.c
Normal file
126
libs/tree_dump/src/scc_tree_dump.c
Normal 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); }
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
49
src/main.c
49
src/main.c
@@ -24,7 +24,7 @@ static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) {
|
||||
} else if (verbose >= 1) {
|
||||
scc_printf(
|
||||
"token [%-8s] `%s` at %s:%d:%d\n", scc_get_tok_name(tok.type),
|
||||
tok.type != SCC_TOK_ENDLINE ? scc_cstring_as_cstr(&tok.lexeme)
|
||||
tok.type != SCC_TOK_ENDLINE ? scc_str_as_cstr(&tok.lexeme)
|
||||
: "\\n",
|
||||
tok.loc.name, tok.loc.line, tok.loc.col);
|
||||
}
|
||||
@@ -42,11 +42,11 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) {
|
||||
break;
|
||||
}
|
||||
if (fp == scc_stdout) {
|
||||
scc_printf("%s", scc_cstring_as_cstr(&tok.lexeme));
|
||||
scc_printf("%s", scc_str_as_cstr(&tok.lexeme));
|
||||
} else {
|
||||
usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme),
|
||||
scc_cstring_len(&tok.lexeme));
|
||||
if (ret != scc_cstring_len(&tok.lexeme)) {
|
||||
usize ret = scc_fwrite(fp, scc_str_as_cstr(&tok.lexeme),
|
||||
scc_str_len(&tok.lexeme));
|
||||
if (ret != scc_str_len(&tok.lexeme)) {
|
||||
LOG_FATAL("Failed to write to file");
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,10 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) {
|
||||
scc_fclose(fp);
|
||||
}
|
||||
|
||||
static void tree_dump_output(const char *str, usize len, void *user) {
|
||||
scc_fprintf(user, "%.*s", (int)len, str);
|
||||
}
|
||||
|
||||
void init_platform(void);
|
||||
|
||||
int main(int argc, const char **argv, const char **envp) {
|
||||
@@ -139,7 +143,7 @@ int main(int argc, const char **argv, const char **envp) {
|
||||
scc_lexer_tok_vec_t pproc_tok_vec;
|
||||
scc_vec_init(pproc_tok_vec);
|
||||
scc_lexer_tok_t tok = {
|
||||
.lexeme = scc_cstring_from_cstr("1"),
|
||||
.lexeme = scc_str_from_cstr("1"),
|
||||
.type = SCC_TOK_INT_LITERAL,
|
||||
.loc.name = "<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
1
src/target.c
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "scc_stdio.h"
|
||||
|
||||
int main(void) {
|
||||
puts("hello world");
|
||||
return 0;
|
||||
}
|
||||
9
tests/simple/12_logic.c
Normal file
9
tests/simple/12_logic.c
Normal 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
8
tests/simple/13_array.c
Normal 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
12
tests/simple/14_pointer.c
Normal 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;
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -2,5 +2,6 @@
|
||||
#define __SCC_STDIO_H__
|
||||
|
||||
extern int puts(const char *str);
|
||||
extern char *gets(char *buff);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user