feat(ir): 实现函数调用和参数处理功能

- 在AST定义中移除函数调用结构体中的冗余name字段
- 实现完整的函数声明和定义处理流程,支持符号表查找
- 添加函数参数引用节点类型,支持参数传递和访问
- 实现函数调用的IR生成,包括参数处理和符号解析
- 添加断言确保节点有效性,提升代码健壮性

fix(ast2ir): 优化类型转换处理逻辑

- 移除多余的注释说明
- 简化参数为空检查逻辑,提高代码简洁性
- 修复函数调用时的符号表查找机制

refactor(ir): 改进IR构建器接口设计

- 修改函数构建相关API,使接口更加清晰
- 添加函数声明集合管理
- 重构内置类型缓存机制

feat(ir2mcode): 完善AMD64代码生成

- 实现函数参数到寄存器的映射
- 添加函数调用约定支持(最多4个参数)
- 实现函数符号和重定位处理
- 添加栈帧管理机制
- 修正栈偏移计算

chore(ir): 清理和优化IR dump输出

- 更新节点类型描述信息
- 改进函数声明和定义的输出格式
- 修正格式化输出中的符号显示问题

style: 代码格式化和命名规范化

- 统一重定位类型枚举命名
- 优化函数参数验证和错误处理
This commit is contained in:
zzy
2026-03-23 16:02:23 +08:00
parent 097dbdcc2a
commit 741171dbba
17 changed files with 356 additions and 152 deletions

View File

@@ -285,7 +285,6 @@ struct scc_ast_expr {
} cond;
// 函数调用
struct {
const char *name;
scc_ast_expr_t *callee;
scc_ast_expr_vec_t args;
} call;

View File

@@ -20,12 +20,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
case SCC_AST_TYPE_POINTER: {
scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR);
// 创建指向类型并添加到程序类型列表
scc_ir_type_ref_t pointee_type =
scc_ast2ir_type(ctx, ast_type->pointer.pointee);
// 注意:我们需要找到一种合适的方式来存储类型信息
// 目前的IR设计中类型信息应该直接存储在类型结构中
ir_type.data.pointer.base = pointee_type;
break;
}
@@ -33,11 +30,9 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
case SCC_AST_TYPE_ARRAY: {
scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY);
// 创建元素类型并添加到程序类型列表
scc_ir_type_ref_t element_type =
scc_ast2ir_type(ctx, ast_type->array.element);
// 将类型添加到程序的类型容器中
ir_type.data.array.base = element_type;
// TODO: 处理数组大小表达式
ir_type.data.array.len = 0; // 暂时设为0
@@ -267,22 +262,20 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
scc_ir_node_ref_vec_t args;
scc_vec_init(args);
// 检查参数是否为空
if (expr->call.args.data != null) {
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;
arg_node = scc_ast2ir_expr(ctx, arg_expr, false);
scc_vec_push(args, arg_node);
}
}
// 创建调用节点(需要查找函数定义)
// TODO: 需要符号表查找函数
scc_ir_node_ref_t func =
scc_ir_builder_call(&ctx->builder, 0, args.data, args.size);
scc_ir_func_ref_t func = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
&ctx->symtab, expr->call.callee->identifier._target->name);
scc_ir_node_ref_t node =
scc_ir_builder_call(&ctx->builder, func, args.data, args.size);
scc_vec_free(args);
return func;
return node;
}
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
@@ -316,6 +309,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
// FIXME hack hashtable
scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
&ctx->node2ir, expr->identifier._target);
Assert(in != 0);
if (is_lvalue) {
return in;
} else {
@@ -548,14 +542,38 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
}
case SCC_AST_DECL_FUNC: {
scc_ir_type_ref_t func_type = scc_ast2ir_type(ctx, decl->func.type);
scc_ir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type);
scc_ir_func_ref_t func_ref =
(usize)scc_hashtable_get(&ctx->symtab, decl->name);
if (func_ref == 0) {
func_ref =
scc_ir_builder_func(&ctx->builder, func_type_ref, decl->name);
scc_hashtable_set(&ctx->symtab, decl->name,
(void *)(usize)func_ref);
scc_vec_push(ctx->builder.cprog.func_decls, func_ref);
}
if (decl->func.body == null) {
// function decl
break;
}
// TODO params name
scc_ir_builder_begin_func(&ctx->builder, decl->name, func_type, null);
scc_ir_builder_begin_func(&ctx->builder, func_ref, null);
scc_ir_func_t *func = scc_ir_ctx_get_func(&ctx->builder.ctx, func_ref);
Assert(func != null);
scc_ir_builder_begin_bblock(&ctx->builder, "entry");
scc_vec_foreach(decl->func.type->function.params, i) {
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_ctx_get_node(&ctx->builder.ctx, param_node_ref);
Assert(param_node != null);
param_node->name = param->name;
scc_hashtable_set(&ctx->node2ir, param,
(void *)(usize)param_node_ref);
}
scc_ast2ir_stmt(ctx, decl->func.body);
scc_ir_builder_end_bblock(&ctx->builder);
scc_ir_builder_end_func(&ctx->builder);
@@ -607,4 +625,6 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) {
ctx->abi = abi;
scc_ir_builder_init(&ctx->builder);
scc_hashtable_init(&ctx->node2ir, 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);
}

View File

@@ -19,6 +19,7 @@ typedef struct scc_ir_builder scc_ir_builder_t;
struct scc_ir_builder {
scc_ir_cprog_ctx_t ctx; /**< 核心上下文 */
scc_ir_cprog_t cprog;
scc_hashtable_t func_decl_set;
// 当前构建位置
scc_ir_func_ref_t current_func; /**< 当前正在构建的函数 */
scc_ir_bblock_ref_t current_bblock; /**< 当前基本块 */
@@ -34,16 +35,18 @@ void scc_ir_builder_init(scc_ir_builder_t *builder);
*/
void scc_ir_builder_drop(scc_ir_builder_t *builder);
scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder,
scc_ir_type_ref_t type_ref,
const char *name);
/**
* @brief 开始构建函数
* @param name 函数
* @param type 函数类型
* @param func_ref 函数引用
* @param param_names 参数名列表可为NULL
* @return 函数引用
* @return void
*/
scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
const char *name,
scc_ir_type_ref_t type,
void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
scc_ir_func_ref_t func_ref,
const char **param_names);
/**
@@ -93,6 +96,10 @@ 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_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 指针操作数

View File

@@ -29,12 +29,6 @@ typedef struct {
// 常量池(常量键 -> 节点引用)
scc_hashtable_t const_pool;
// 内置类型缓存
scc_ir_type_ref_t builtin_i32;
scc_ir_type_ref_t builtin_i1;
scc_ir_type_ref_t builtin_void;
scc_ir_node_ref_t builtin_zero_i32;
} scc_ir_cprog_ctx_t;
/**

View File

@@ -207,7 +207,7 @@ struct scc_ir_node {
scc_ir_bblock_ref_t target_bblock;
} jump;
struct {
scc_ir_func_ref_t callee;
scc_ir_func_ref_t callee; // TODO function pointer call
scc_ir_node_ref_vec_t args;
} call;
struct {
@@ -217,9 +217,9 @@ struct scc_ir_node {
};
typedef struct scc_ir_cprog {
scc_ir_node_ref_vec_t global_vals;
scc_ir_func_ref_vec_t func_defs;
scc_ir_node_ref_vec_t func_decls;
scc_ir_node_ref_vec_t global_vals; /* 全局变量 */
scc_ir_func_ref_vec_t func_defs; /* 所有函数定义 */
scc_ir_func_ref_vec_t func_decls; /* 所有函数包括定义的声明 */
} scc_ir_cprog_t;
#endif /* __SCC_IR_DEF_H__ */

View File

@@ -14,33 +14,44 @@ void scc_ir_builder_drop(scc_ir_builder_t *builder) {
scc_ir_ctx_drop(&builder->ctx);
}
scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
const char *name,
scc_ir_type_ref_t type,
const char **param_names) {
scc_ir_func_t func = {0};
// 初始化参数和基本块向量
func.name = name;
func.type = type;
scc_ir_func_ref_t scc_ir_builder_func(scc_ir_builder_t *builder,
scc_ir_type_ref_t type_ref,
const char *name) {
scc_ir_func_t func = {
.name = name,
.type = type_ref,
};
scc_vec_init(func.params);
scc_vec_init(func.bblocks);
// 创建函数并设置为当前函数
scc_ir_func_ref_t func_ref = scc_ir_ctx_new_func(&builder->ctx, &func);
builder->current_func = func_ref;
// 如果提供了参数名称,则创建参数节点
if (param_names == null) {
return func_ref;
}
void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
scc_ir_func_ref_t func_ref,
const char **param_names) {
// 创建函数并设置为当前函数
builder->current_func = func_ref;
scc_ir_func_t *func_ptr = scc_ir_ctx_get_func(&builder->ctx, func_ref);
scc_ir_type_t *func_type = scc_ir_ctx_get_type(&builder->ctx, type);
scc_ir_type_t *func_type =
scc_ir_ctx_get_type(&builder->ctx, func_ptr->type);
if (func_type == null || func_type->tag != SCC_IR_TYPE_FUNC) {
LOG_ERROR("Invalid function type");
return func_ref;
return;
}
if (func_ptr == null) {
LOG_ERROR("Invalid function reference");
return;
}
if (scc_vec_size(func_ptr->bblocks) != 0 ||
scc_vec_size(func_ptr->params) != 0) {
LOG_FATAL("Multiple function definitions");
return;
}
scc_vec_foreach(func_type->data.function.params, i) {
@@ -48,9 +59,10 @@ scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
scc_vec_at(func_type->data.function.params, i);
scc_ir_node_t param_node = {0};
param_node.tag = SCC_IR_NODE_NULL; // 参数节点标记
param_node.tag = SCC_IR_NODE_FUNC_ARG_REF; // 参数节点标记
param_node.type = param_type;
param_node.name = param_names[i];
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 =
@@ -58,7 +70,7 @@ scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
scc_vec_push(func_ptr->params, param_ref);
}
return func_ref;
return;
}
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
@@ -144,6 +156,21 @@ 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;
node.type = type;
node.name = name;
node.data.arg_ref.idx = arg_idx;
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &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};

View File

@@ -213,20 +213,7 @@ scc_ir_type_ref_t scc_ir_ctx_new_type(scc_ir_cprog_ctx_t *ctx,
return (scc_ir_type_ref_t)(uintptr_t)existing;
}
// 创建新类型
unsigned new_uid = ctx->type_uid++;
scc_vec_push(ctx->types, *type);
// 添加到UID映射
usize idx = ctx->types.size - 1;
scc_hashtable_set(&ctx->uid2types, &new_uid, (void *)idx);
// 添加到去重表
scc_hashtable_set(&ctx->type_uniquing,
&ctx->types.data[idx], // 使用向量中的地址作为键
(void *)(uintptr_t)new_uid);
return new_uid;
CREATE_ENTITY(ctx, ctx->types, type_uid, type, uid2types);
}
scc_ir_node_ref_t scc_ir_ctx_new_node(scc_ir_cprog_ctx_t *ctx,
@@ -292,11 +279,12 @@ scc_ir_func_t *scc_ir_ctx_get_func(scc_ir_cprog_ctx_t *ctx,
#undef GET_ENTITY_INDEX
// 内置类型和常量缓存
static scc_ir_type_ref_t cached_i32_type = 0;
static scc_ir_node_ref_t cached_zero_const = 0;
// // 内置类型和常量缓存
// static scc_ir_type_ref_t cached_i32_type = 0;
// static scc_ir_node_ref_t cached_zero_const = 0;
scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) {
scc_ir_type_ref_t cached_i32_type = 0;
if (cached_i32_type == 0) {
scc_ir_type_t i32_type = {.tag = SCC_IR_TYPE_I32};
cached_i32_type = scc_ir_ctx_new_type(ctx, &i32_type);
@@ -305,6 +293,7 @@ scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) {
}
scc_ir_node_ref_t scc_ir_ctx_get_builtin_zero(scc_ir_cprog_ctx_t *ctx) {
scc_ir_node_ref_t cached_zero_const = 0;
if (cached_zero_const == 0) {
scc_ir_node_t zero_node = {.tag = SCC_IR_NODE_CONST_INT,
.type = scc_ir_ctx_get_builtin_i32(ctx),
@@ -333,7 +322,7 @@ scc_ir_node_ref_t scc_ir_ctx_get_i32_const(scc_ir_cprog_ctx_t *ctx, i32 value) {
.type = scc_ir_ctx_get_builtin_i32(ctx),
.data.const_int.int32 = value};
const_node.name = "";
const_node.name = null;
return scc_ir_ctx_new_node(ctx, &const_node);
}

View File

@@ -13,12 +13,25 @@
// 获取IR节点类型的字符串表示
static const char *get_node_type_str(scc_ir_node_tag_t tag) {
static const char *node_types[] = {
[SCC_IR_NODE_NULL] = "Null", [SCC_IR_NODE_CONST_INT] = "ConstInt",
[SCC_IR_NODE_ALLOC] = "Alloc", [SCC_IR_NODE_LOAD] = "Load",
[SCC_IR_NODE_STORE] = "Store", [SCC_IR_NODE_GET_PTR] = "GetElementPtr",
[SCC_IR_NODE_OP] = "Op", [SCC_IR_NODE_BRANCH] = "Branch",
[SCC_IR_NODE_JUMP] = "Jump", [SCC_IR_NODE_CALL] = "Call",
[SCC_IR_NODE_RET] = "Return",
[SCC_IR_NODE_NULL] = "Null",
[SCC_IR_NODE_CONST_INT] = "ConstInt",
[SCC_IR_NODE_CONST_UINT] = "ConstUint",
[SCC_IR_NODE_CONST_FLOAT] = "ConstFloat",
[SCC_IR_NODE_CONV] = "Convert", ///< 类型转换
[SCC_IR_NODE_FUNC_ARG_REF] = "FuncArgRef", ///< 函数参数引用
[SCC_IR_NODE_BLOCK_ARG_REF] = "BlockArgRef", ///< 基本块参数引用
[SCC_IR_NODE_ALLOC] = "Alloc", ///< 分配内存(stack)
[SCC_IR_NODE_GLOBAL_ALLOC] = "GlobalAlloc", ///< 全局分配(bss)
[SCC_IR_NODE_LOAD] = "Load", ///< 加载数据
[SCC_IR_NODE_STORE] = "Store", ///< 存储数据
[SCC_IR_NODE_GET_PTR] = "GetPtr", ///< 获取指针
[SCC_IR_NODE_GET_ELEM_PTR] =
"GetElemPtr", ///< 获取元素指针(used by array)
[SCC_IR_NODE_OP] = "Op", ///< 二元运算
[SCC_IR_NODE_BRANCH] = "Branch", ///< 有条件分支
[SCC_IR_NODE_JUMP] = "Jump", ///< 无条件跳转
[SCC_IR_NODE_CALL] = "Call", ///< 调用函数
[SCC_IR_NODE_RET] = "Ret", ///< 函数返回
};
if (tag >= 0 && (usize)tag < sizeof(node_types) / sizeof(node_types[0]) &&
@@ -713,10 +726,10 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
args_remaining = sizeof(args_buf) - (args_p - args_buf);
}
format_node_ref_or_value(ctx, node_name, sizeof(node_name),
node->data.call.callee);
p += scc_snprintf(p, remaining, "call @%s(%s)", node_name, args_buf);
scc_ir_func_t *func =
scc_ir_ctx_get_func(ctx->ir_ctx, node->data.call.callee);
p += scc_snprintf(p, remaining, "call @%s(%s)",
func ? func->name : null, args_buf);
break;
}
@@ -731,6 +744,11 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
}
break;
case SCC_IR_NODE_FUNC_ARG_REF: {
p += scc_snprintf(p, remaining, "arg[%zu]", node->data.arg_ref.idx);
break;
}
default:
p += scc_snprintf(p, remaining, "<%s node %u>",
get_node_type_str(node->tag), node_ref);
@@ -796,7 +814,7 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx,
if (i > 0)
PRINT_NODE(ctx->dump_ctx, ", ");
scc_ir_node_ref_t param_ref = scc_vec_at(func->params, i);
PRINT_NODE(ctx->dump_ctx, "%%");
PRINT_NODE(ctx->dump_ctx, "%");
scc_ir_node_t *param_node =
scc_ir_ctx_get_node(ctx->ir_ctx, param_ref);
if (param_node && param_node->name && param_node->name[0] != '\0') {
@@ -813,11 +831,8 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx,
PRINT_NODE(ctx->dump_ctx, "()");
}
// 如果有返回类型
if (func->type != 0) {
PRINT_NODE(ctx->dump_ctx, " -> ");
PRINT_NODE(ctx->dump_ctx, ": ");
scc_ir_dump_type_linear(ctx, func->type);
}
PRINT_NODE(ctx->dump_ctx, " {\n");
@@ -833,6 +848,13 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx,
// 线性输出整个程序
void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->cprog->func_decls, i) {
scc_ir_func_ref_t func_decl = scc_vec_at(ctx->cprog->func_decls, i);
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_decl);
Assert(func != null);
if (scc_vec_size(func->bblocks) == 0)
scc_ir_dump_func_linear(ctx, func_decl);
}
scc_vec_foreach(ctx->cprog->func_defs, i) {
scc_ir_dump_func_linear(ctx, scc_vec_at(ctx->cprog->func_defs, i));
}

View File

@@ -7,6 +7,7 @@
typedef enum {
SCC_REG_KIND_UNDEF,
SCC_REG_KIND_FUNC_ARG,
SCC_REG_KIND_GPR, ///< 通用寄存器(整数)
SCC_REG_KIND_FPR, ///< 浮点数寄存器
SCC_REG_KIND_STACK, ///< 栈

View File

@@ -12,6 +12,8 @@ typedef struct {
scc_mcode_t mcode;
sccf_builder_t builder;
// FIXME
usize stack_size;
scc_reg_alloc_t reg_alloc;
scc_hashtable_t *noderef2regloc;
} scc_ir2mcode_ctx_t;

View File

@@ -4,7 +4,7 @@
#include <scc_ir2mcode.h>
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
scc_ir_bblock_ref_t node_ref) {
scc_ir_node_ref_t node_ref) {
Assert(ctx != null && loc != null);
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (node == null) {
@@ -27,6 +27,17 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
case SCC_IR_NODE_CONST_FLOAT:
TODO();
break;
case SCC_IR_NODE_FUNC_ARG_REF: {
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_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.idx = 8 * node->data.arg_ref.idx;
*loc = arg_loc;
return;
}
default:
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
(void *)(usize)node_ref);
@@ -47,8 +58,9 @@ static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) {
}
break;
case SCC_REG_KIND_STACK:
// FIXME -8 for rdp
scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP,
-loc->idx);
-loc->idx - 8);
break;
case SCC_REG_KIND_IMM:
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32
@@ -67,7 +79,8 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc,
}
break;
case SCC_REG_KIND_STACK:
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx,
// FIXME -8 for rdp
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8,
reg);
break;
case SCC_REG_KIND_IMM:
@@ -96,10 +109,13 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
switch (node->tag) {
case SCC_IR_NODE_CONV: ///< 类型转换
case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用
case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用
LOG_FATAL("Unsupported node type: %d", node->tag);
break;
///< 函数参数引用
case SCC_IR_NODE_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)
break;
@@ -127,7 +143,8 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
case SCC_IR_NODE_GET_PTR: ///< 获取指针
case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array)
TODO();
case SCC_IR_NODE_OP: ///< 二元运算
///< 二元运算
case SCC_IR_NODE_OP: {
scc_reg_loc_t loc_lhs;
parse_location(ctx, &loc_lhs, node->data.op.lhs);
scc_reg_loc_t loc_rhs;
@@ -216,6 +233,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
// 将 RAX 中的结果存储到 res 位置
store_value_from_reg(&ctx->mcode, &loc_res, SCC_AMD64_RAX);
break;
}
///< 有条件分支
case SCC_IR_NODE_BRANCH: {
scc_reg_loc_t loc;
@@ -257,7 +275,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
R9 不稳定的 第四个整型自变量
*/
scc_vec_foreach(node->data.call.args, i) {
parse_location(ctx, &loc, node->data.branch.cond);
parse_location(ctx, &loc, scc_vec_at(node->data.call.args, i));
if (i == 0) {
load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
@@ -280,9 +298,22 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
}
scc_mcode_amd64_call_rel32(&ctx->mcode, 0);
usize sym_idx = sccf_builder_get_symbol_idx(&ctx->builder, func->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->mcode.mcode) - 4,
.addend = 4,
.sect_type = SCCF_SECT_CODE,
.sym_idx = sym_idx,
});
// 处理返回值
scc_ir_type_t *ret_type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
scc_ir_type_t *func_type = scc_ir_ctx_get_type(ctx->ir_ctx, func->type);
Assert(func_type);
scc_ir_type_t *ret_type =
scc_ir_ctx_get_type(ctx->ir_ctx, func_type->data.function.ret_type);
if (ret_type && ret_type->tag != SCC_IR_TYPE_VOID) {
parse_location(ctx, &loc, node_ref);
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RAX);
@@ -296,12 +327,13 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
parse_location(ctx, &loc, node->data.ret.ret_val);
load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RAX);
}
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RSP, SCC_AMD64_RBP);
scc_mcode_amd64_add_rsp_imm32(&ctx->mcode, ctx->stack_size);
scc_mcode_amd64_pop_r64(&ctx->mcode, SCC_AMD64_RBP);
scc_mcode_amd64_ret(&ctx->mcode);
break;
}
default:
LOG_FATAL("unknown node type: %d", node->tag);
UNREACHABLE();
break;
}
@@ -325,7 +357,9 @@ static int equal_func(const void *key1, const void *key2) {
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func);
// 对齐到 16 字节
usize stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15;
// FIXME
ctx->stack_size += 8; ///< for rbp
ctx->stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15;
usize bblock_cnt = scc_vec_size(func->bblocks);
usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize));
@@ -341,8 +375,28 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
scc_vec_init(patches);
scc_mcode_amd64_push_r64(&ctx->mcode, SCC_AMD64_RBP);
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RBP, SCC_AMD64_RSP);
scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, stack_size);
scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, ctx->stack_size);
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->mcode, SCC_AMD64_RBP,
SCC_AMD64_RSP, ctx->stack_size);
scc_reg_loc_t loc;
scc_vec_foreach(func->params, i) {
// scc_ir_node_t *param =
// scc_ir_ctx_get_node(ctx->ir_ctx, );
scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i);
parse_location(ctx, &loc, node_ref);
if (i == 0) {
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RCX);
} else if (i == 1) {
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RDX);
} else if (i == 2) {
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R8);
} else if (i == 3) {
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R9);
} else {
LOG_FATAL("not support more than 4 args");
}
// scc_mcode_amd64_push_r64();
}
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
@@ -367,12 +421,8 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
usize target_off = bblock_offsets[target_id];
usize next_off = p->pos;
i32 rel = (i32)(target_off - next_off);
// 写入到指令的偏移字段(小端)
// FIXME 写入到指令的偏移字段(小端)
*(u32 *)(&buf[p->pos - 4]) = rel;
// buf[p->pos + 1] = (u8)(rel >> 0);
// buf[p->pos + 2] = (u8)(rel >> 8);
// buf[p->pos + 3] = (u8)(rel >> 16);
// buf[p->pos + 4] = (u8)(rel >> 24);
}
scc_free(bblock_offsets);
scc_vec_free(patches);
@@ -382,6 +432,39 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack, ctx->ir_ctx);
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_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
if (!func) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t sym = {0};
if (scc_vec_size(func->bblocks)) {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_CODE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_FUNC,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
} else {
sym = (sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_NONE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
}
usize sym_idx =
sccf_builder_add_symbol(&ctx->builder, func->name, &sym);
Assert(sym_idx != 0);
}
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_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
@@ -389,16 +472,10 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
LOG_ERROR("invalid function reference");
return;
}
sccf_sym_t sym = {
.sccf_sect_offset = scc_vec_size(ctx->mcode.mcode),
.sccf_sect_type = SCCF_SECT_CODE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 0,
.sccf_sym_type = SCCF_SYM_TYPE_FUNC,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
};
sccf_builder_add_symbol(&ctx->builder, func->name, &sym);
sccf_sym_t *sym =
sccf_builder_get_symbol_unsafe(&ctx->builder, func->name);
Assert(sym != null);
sym->sccf_sect_offset = scc_vec_size(ctx->mcode.mcode);
parse_function(ctx, func);
}
sccf_sect_data_t text_section;
@@ -409,4 +486,28 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
sccf_sect_data_t data_section;
scc_vec_init(data_section);
sccf_builder_add_data_section(&ctx->builder, &data_section);
u8 *buf = scc_vec_unsafe_get_data(ctx->mcode.mcode);
scc_vec_foreach(ctx->builder.relocs, i) {
sccf_reloc_t *reloc = &scc_vec_at(ctx->builder.relocs, i);
if (reloc->sym_idx == 0) {
Panic("relocate to an invalid symbol");
}
sccf_sym_t *sym = &scc_vec_at(ctx->builder.symtab, reloc->sym_idx);
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;
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
}
}
// FIXME
ctx->builder.entry_symbol_name = "main";
}

View File

@@ -23,7 +23,17 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
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);
loc.kind = SCC_REG_KIND_FUNC_ARG;
loc.idx = i;
ctx->alloc_stack_size += 8;
scc_hashtable_set(&ctx->node_ref2reg_loc, (void *)(usize)node_ref,
(void *)scc_vec_size(ctx->reg_loc_vec));
break;
}
scc_vec_foreach(func->bblocks, i) {
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
scc_ir_bblock_t *bblock =
@@ -33,8 +43,6 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
scc_ir_node_ref_t node_ref = scc_vec_at(bblock->instrs, j);
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
Assert(node != null);
scc_reg_loc_t loc;
loc.kind = SCC_REG_KIND_UNDEF;
switch (node->tag) {
case SCC_IR_NODE_LOAD:
@@ -51,8 +59,12 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
break;
}
case SCC_IR_NODE_CALL: {
scc_ir_type_t *ret_type =
scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
// 处理返回值
scc_ir_type_t *func_type =
scc_ir_ctx_get_type(ctx->ir_ctx, func->type);
Assert(func_type);
scc_ir_type_t *ret_type = scc_ir_ctx_get_type(
ctx->ir_ctx, func_type->data.function.ret_type);
if (ret_type && ret_type->tag != SCC_IR_TYPE_VOID) {
loc.kind = SCC_REG_KIND_STACK;
loc.idx = ctx->alloc_stack_size;

View File

@@ -74,8 +74,9 @@ typedef enum {
/** 重定位类型 */
typedef enum {
SCCF_RELOC_ABS = 1, ///< 绝对地址
SCCF_RELOC_REL = 2, ///< 对地址
SCCF_RELOC_TYPE_EMPTY = 0, ///< 空展位符
SCCF_RELOC_TYPE_ABS = 1, ///< 对地址
SCCF_RELOC_TYPE_REL = 2, ///< 相对地址
} sccf_reloc_type_t;
/**
@@ -121,7 +122,7 @@ typedef struct {
* @brief SCCF重定向条目
*/
typedef struct {
sccf_enum_t type; ///< 重定位类型
sccf_enum_t reloc_type; ///< 重定位类型
sccf_enum_t sect_type; ///< 需要重定位的段类型(代码段/数据段)
sccf_size_t sym_idx; ///< 符号索引(重定向指向的符号)
sccf_size_t offset; ///< 在段中的偏移量(用于重定向的地址)

View File

@@ -7,6 +7,7 @@
typedef struct {
sccf_t sccf;
int aligned;
const char *entry_symbol_name;
sccf_strtab_t strtab;
sccf_reloc_vec_t relocs;
sccf_sym_vec_t symtab;
@@ -19,10 +20,16 @@ void sccf_builder_init(sccf_builder_t *builder);
usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name,
sccf_sym_t *sym);
usize sccf_builder_get_symbol_idx(sccf_builder_t *builder, const char *name);
static inline sccf_sym_t *
sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, usize idx) {
sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, const char *name) {
usize idx = sccf_builder_get_symbol_idx(builder, name);
if (idx == 0) {
return null;
}
return &scc_vec_at(builder->symtab, idx);
}
void sccf_builder_add_reloc(sccf_builder_t *builder, sccf_reloc_t reloc);
/**

View File

@@ -13,6 +13,8 @@ void sccf_builder_init(sccf_builder_t *builder) {
scc_vec_init(builder->relocs);
scc_vec_init(builder->symtab);
builder->entry_symbol_name = null;
///< Push null
scc_vec_push(builder->strtab, (char)'\0');
///< Push null
@@ -23,21 +25,26 @@ usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name,
sccf_sym_t *sym) {
usize offset = 0;
offset = (usize)scc_hashtable_get(&builder->str2offset, name);
const char *key = &scc_vec_at(builder->strtab, offset);
if (offset == 0) {
offset = scc_vec_size(builder->strtab);
scc_hashtable_set(&builder->str2offset, name, (void *)offset);
while (*name) {
scc_vec_push(builder->strtab, *name);
name++;
}
scc_vec_push(builder->strtab, '\0');
key = &scc_vec_at(builder->strtab, offset);
scc_hashtable_set(&builder->str2offset, key, (void *)offset);
}
sym->name_offset = offset;
usize sym_idx = scc_vec_size(builder->symtab);
offset = (usize)scc_hashtable_get(&builder->str2sym, name);
offset = (usize)scc_hashtable_get(&builder->str2sym, key);
if (offset == 0) {
scc_hashtable_set(&builder->str2sym, name, (void *)sym_idx);
scc_hashtable_set(&builder->str2sym, key, (void *)sym_idx);
} else {
LOG_ERROR("symbol %s already exists", key);
}
scc_vec_push(builder->symtab, *sym);
return sym_idx;
@@ -62,9 +69,19 @@ void sccf_builder_add_section(sccf_builder_t *builder,
}
const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
// TODO symtab strtab reloc
// sccf_sect_header_t symtab_header;
// sccf_sect_data_t symtab_data;
if (builder->entry_symbol_name == null) {
builder->sccf.header.entry_point = 0;
} else {
sccf_sym_t *sym =
sccf_builder_get_symbol_unsafe(builder, builder->entry_symbol_name);
if (sym == null || sym->sccf_sect_type != SCCF_SECT_CODE) {
LOG_ERROR("entry symbol %s not found");
builder->sccf.header.entry_point = 0;
} else {
builder->sccf.header.entry_point = sym->sccf_sect_offset;
}
}
sccf_sect_header_t sect_header;
if (scc_vec_size(builder->strtab)) {
sect_header = (sccf_sect_header_t){

View File

@@ -167,7 +167,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
scc_pe_buffer_t idata_buffer =
scc_pe_construct_idata(&idata_builder, &idata_range);
u32 entry_point_offset = 0;
u32 entry_point_offset = sccf->header.entry_point;
u64 base_address = 0x140000000;
u32 entry_point = code_range.virual_address + entry_point_offset;
scc_pe_config_t config = (scc_pe_config_t){
@@ -197,6 +197,9 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
scc_vec_foreach(relocs, i) {
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
continue;
}
sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx);
const char *name = &scc_vec_at(strtab, sym->name_offset);
@@ -212,7 +215,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
}
Assert(rva != 0);
if (reloc->type == SCCF_RELOC_ABS) {
if (reloc->reloc_type == SCCF_RELOC_TYPE_ABS) {
TODO();
}
Assert(reloc->sect_type == SCCF_SECT_CODE);

View File

@@ -51,16 +51,18 @@ int main() {
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
});
sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4,
sccf_builder_add_reloc(&builder,
(sccf_reloc_t){.addend = 4,
.offset = 7,
.sect_type = SCCF_SECT_CODE,
.sym_idx = str_idx,
.type = SCCF_RELOC_REL});
sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4,
.reloc_type = SCCF_RELOC_TYPE_REL});
sccf_builder_add_reloc(&builder,
(sccf_reloc_t){.addend = 4,
.offset = 13,
.sect_type = SCCF_SECT_CODE,
.sym_idx = puts_idx,
.type = SCCF_RELOC_REL});
.reloc_type = SCCF_RELOC_TYPE_REL});
const sccf_t *sccf = sccf_builder_to_sccf(&builder);
scc_pe_builder_t pe_builder;