fix(abi): 修复void类型的ABI计算缺少break语句
在scc_type_abi.c文件中,void类型的case分支缺少break语句, 导致执行流程错误地进入下一个case分支。 feat(ast): 为参数声明添加索引字段 在ast_def.h头文件中为参数声明结构体添加param_idx字段, 用于跟踪参数在函数参数列表中的位置索引。 feat(ast): 更新参数初始化函数以支持索引参数 修改scc_ast.h中的scc_ast_decl_param_init函数签名, 添加参数索引idx参数,并将该值存储到参数声明结构体中。 feat(ast2ir): 添加IR转换上下文的值使用提示选项 在ast2ir.h中为scc_ast2ir_ctx_t结构体添加hint_using_value字段, 控制参数转换时是使用值还是分配内存的方式。 fix(ast2ir): 正确处理void类型到IR的转换 当遇到大小为0的类型(如void)时,直接返回void类型, 而不是尝试匹配其他大小分支。 refactor(ast2ir): 统一基本块引用类型为value_ref 将逻辑表达式、条件语句、循环语句中的基本块引用类型 从bblock_ref_t改为value_ref_t,保持类型一致性。 fix(ast2ir): 修正函数引用空值检查 使用SCC_IR_REF_nullptr常量替代0进行函数引用的空值检查, 提高代码的可读性和正确性。 refactor(ast2ir): 简化参数处理逻辑 移除不必要的函数参数获取和命名设置逻辑, 通过递归调用scc_ast2ir_decl来处理参数声明。 feat(ast2ir): 实现参数声明到IR的转换 为参数声明添加完整的IR转换逻辑,包括类型转换、 参数引用创建和内存分配处理。 refactor(ast2ir): 更新哈希表初始化接口 适配新的哈希表初始化函数签名,添加userdata参数支持, 并初始化hint_using_value字段为false。 refactor(ir): 移除函数参数的预分配逻辑 删除IR构建器中函数参数的预分配和循环添加逻辑, 简化函数开始构建的处理流程。 refactor(ir): 更新类型哈希表键值处理 修改类型哈希表的哈希和比较函数以接受模块参数, 正确处理空引用情况并支持新的键值传递方式。 fix(ir): 修复IR转储中的字符串格式 移除IR函数转储时多余的换行符,确保输出格式正确。 refactor(ir): 更新模块哈希表初始化 适配哈希表初始化接口变更,添加userdata参数, 并为各种向量预留UID 0作为无效引用。 fix(ir): 修复模块清理中的循环起始索引 将模块清理循环的起始索引从0改为1,跳过预留的 无效引用项,避免访问空指针。 refactor(ir): 调整向量和哈希表操作顺序 调整模块中向量push和哈希表set的操作顺序, 确保数据一致性和正确的UID分配。 chore(build): 移除ir2mcode模块相关文件 移除ir2mcode相关的头文件和源文件,这些组件 将在后续重构中重新设计或替换。
This commit is contained in:
@@ -9,6 +9,7 @@ void scc_abi_compute_ast_type_layout(const scc_abi_type_calc_t *ctx, void *type,
|
|||||||
switch (ast_type->builtin.type) {
|
switch (ast_type->builtin.type) {
|
||||||
case SCC_AST_BUILTIN_TYPE_VOID:
|
case SCC_AST_BUILTIN_TYPE_VOID:
|
||||||
kind = SCC_ABI_TYPE_VOID;
|
kind = SCC_ABI_TYPE_VOID;
|
||||||
|
break;
|
||||||
case SCC_AST_BUILTIN_TYPE_CHAR:
|
case SCC_AST_BUILTIN_TYPE_CHAR:
|
||||||
kind = SCC_ABI_TYPE_CHAR;
|
kind = SCC_ABI_TYPE_CHAR;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -429,6 +429,7 @@ struct scc_ast_decl {
|
|||||||
// 参数声明
|
// 参数声明
|
||||||
struct {
|
struct {
|
||||||
scc_ast_type_t *type;
|
scc_ast_type_t *type;
|
||||||
|
int param_idx;
|
||||||
} param;
|
} param;
|
||||||
// 结构体/联合/枚举声明
|
// 结构体/联合/枚举声明
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -74,12 +74,14 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
|||||||
// name can be nullptr
|
// name can be nullptr
|
||||||
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
||||||
scc_ast_type_t *type,
|
scc_ast_type_t *type,
|
||||||
const char *name, scc_pos_t loc) {
|
const char *name, int idx,
|
||||||
|
scc_pos_t loc) {
|
||||||
Assert(decl != nullptr && type != nullptr);
|
Assert(decl != nullptr && type != nullptr);
|
||||||
decl->base.loc = loc;
|
decl->base.loc = loc;
|
||||||
decl->base.type = SCC_AST_DECL_PARAM;
|
decl->base.type = SCC_AST_DECL_PARAM;
|
||||||
decl->name = name;
|
decl->name = name;
|
||||||
decl->param.type = type;
|
decl->param.type = type;
|
||||||
|
decl->param.param_idx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
|
static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ typedef struct {
|
|||||||
scc_hashtable_t symtab; ///< symbol 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_abi_type_calc_t *abi;
|
const scc_abi_type_calc_t *abi;
|
||||||
|
cbool hint_using_value; // 转换时尽可能使用value而不是alloc
|
||||||
} scc_ast2ir_ctx_t;
|
} scc_ast2ir_ctx_t;
|
||||||
|
|
||||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ static scc_ir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx,
|
|||||||
// 映射内置类型
|
// 映射内置类型
|
||||||
ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout);
|
ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout);
|
||||||
switch (layout.size) {
|
switch (layout.size) {
|
||||||
|
case 0:
|
||||||
|
return scc_ir_builder_type_void(&ctx->builder);
|
||||||
case 1:
|
case 1:
|
||||||
return scc_ir_builder_type_i8(&ctx->builder);
|
return scc_ir_builder_type_i8(&ctx->builder);
|
||||||
case 2:
|
case 2:
|
||||||
@@ -229,9 +231,9 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
// scc_ir_bblock_ref_t start_block =
|
// scc_ir_bblock_ref_t start_block =
|
||||||
// scc_ir_builder_current_bblock(&ctx->builder);
|
// scc_ir_builder_current_bblock(&ctx->builder);
|
||||||
|
|
||||||
scc_ir_bblock_ref_t right_block =
|
scc_ir_value_ref_t right_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "logic_right");
|
scc_ir_builder_bblock(&ctx->builder, "logic_right");
|
||||||
scc_ir_bblock_ref_t end_block =
|
scc_ir_value_ref_t end_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "logic_end");
|
scc_ir_builder_bblock(&ctx->builder, "logic_end");
|
||||||
|
|
||||||
// 为结果创建临时存储空间
|
// 为结果创建临时存储空间
|
||||||
@@ -248,7 +250,7 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
|
|
||||||
if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) {
|
if (expr->binary.op == SCC_AST_OP_LOGICAL_AND) {
|
||||||
// a && b
|
// a && b
|
||||||
scc_ir_bblock_ref_t false_block =
|
scc_ir_value_ref_t false_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "and_false");
|
scc_ir_builder_bblock(&ctx->builder, "and_false");
|
||||||
|
|
||||||
// 如果左操作数为0,结果为0(短路)
|
// 如果左操作数为0,结果为0(短路)
|
||||||
@@ -276,7 +278,7 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
|
|
||||||
} else { // SCC_AST_OP_LOGICAL_OR
|
} else { // SCC_AST_OP_LOGICAL_OR
|
||||||
// a || b
|
// a || b
|
||||||
scc_ir_bblock_ref_t true_block =
|
scc_ir_value_ref_t true_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "or_true");
|
scc_ir_builder_bblock(&ctx->builder, "or_true");
|
||||||
|
|
||||||
// 如果左操作数非0,结果为1(短路)
|
// 如果左操作数非0,结果为1(短路)
|
||||||
@@ -708,13 +710,13 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
|||||||
\ /
|
\ /
|
||||||
merge_block
|
merge_block
|
||||||
*/
|
*/
|
||||||
scc_ir_bblock_ref_t true_block =
|
scc_ir_value_ref_t true_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "if_true");
|
scc_ir_builder_bblock(&ctx->builder, "if_true");
|
||||||
|
|
||||||
scc_ir_bblock_ref_t false_block =
|
scc_ir_value_ref_t false_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "if_false");
|
scc_ir_builder_bblock(&ctx->builder, "if_false");
|
||||||
|
|
||||||
scc_ir_bblock_ref_t merge_block =
|
scc_ir_value_ref_t merge_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "if_merge");
|
scc_ir_builder_bblock(&ctx->builder, "if_merge");
|
||||||
|
|
||||||
scc_ir_value_ref_t cond_node =
|
scc_ir_value_ref_t cond_node =
|
||||||
@@ -738,11 +740,11 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_STMT_WHILE: {
|
case SCC_AST_STMT_WHILE: {
|
||||||
scc_ir_bblock_ref_t cond_block =
|
scc_ir_value_ref_t cond_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "while_cond");
|
scc_ir_builder_bblock(&ctx->builder, "while_cond");
|
||||||
scc_ir_bblock_ref_t body_block =
|
scc_ir_value_ref_t body_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "while_body");
|
scc_ir_builder_bblock(&ctx->builder, "while_body");
|
||||||
scc_ir_bblock_ref_t exit_block =
|
scc_ir_value_ref_t exit_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "while_exit");
|
scc_ir_builder_bblock(&ctx->builder, "while_exit");
|
||||||
|
|
||||||
scc_ir_builder_jump(&ctx->builder, cond_block);
|
scc_ir_builder_jump(&ctx->builder, cond_block);
|
||||||
@@ -760,11 +762,11 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_STMT_DO_WHILE: {
|
case SCC_AST_STMT_DO_WHILE: {
|
||||||
scc_ir_bblock_ref_t cond_block =
|
scc_ir_value_ref_t cond_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "do_while_cond");
|
scc_ir_builder_bblock(&ctx->builder, "do_while_cond");
|
||||||
scc_ir_bblock_ref_t body_block =
|
scc_ir_value_ref_t body_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "do_while_body");
|
scc_ir_builder_bblock(&ctx->builder, "do_while_body");
|
||||||
scc_ir_bblock_ref_t exit_block =
|
scc_ir_value_ref_t exit_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "do_while_exit");
|
scc_ir_builder_bblock(&ctx->builder, "do_while_exit");
|
||||||
|
|
||||||
scc_ir_builder_jump(&ctx->builder, body_block);
|
scc_ir_builder_jump(&ctx->builder, body_block);
|
||||||
@@ -782,11 +784,11 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_STMT_FOR: {
|
case SCC_AST_STMT_FOR: {
|
||||||
scc_ir_bblock_ref_t cond_block =
|
scc_ir_value_ref_t cond_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "for_while_cond");
|
scc_ir_builder_bblock(&ctx->builder, "for_while_cond");
|
||||||
scc_ir_bblock_ref_t body_block =
|
scc_ir_value_ref_t body_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "for_while_body");
|
scc_ir_builder_bblock(&ctx->builder, "for_while_body");
|
||||||
scc_ir_bblock_ref_t exit_block =
|
scc_ir_value_ref_t exit_block =
|
||||||
scc_ir_builder_bblock(&ctx->builder, "for_while_exit");
|
scc_ir_builder_bblock(&ctx->builder, "for_while_exit");
|
||||||
|
|
||||||
if (stmt->for_stmt.init) {
|
if (stmt->for_stmt.init) {
|
||||||
@@ -928,7 +930,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
scc_ir_type_ref_t func_type_ref = 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 =
|
scc_ir_func_ref_t func_ref =
|
||||||
(usize)scc_hashtable_get(&ctx->symtab, decl->name);
|
(usize)scc_hashtable_get(&ctx->symtab, decl->name);
|
||||||
if (func_ref == 0) {
|
if (func_ref == SCC_IR_REF_nullptr) {
|
||||||
func_ref =
|
func_ref =
|
||||||
scc_ir_builder_func(&ctx->builder, func_type_ref, decl->name);
|
scc_ir_builder_func(&ctx->builder, func_type_ref, decl->name);
|
||||||
scc_hashtable_set(&ctx->symtab, decl->name,
|
scc_hashtable_set(&ctx->symtab, decl->name,
|
||||||
@@ -941,22 +943,14 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ir_builder_begin_func(&ctx->builder, func_ref, nullptr);
|
scc_ir_builder_begin_func(&ctx->builder, func_ref, nullptr);
|
||||||
scc_ir_func_t *func =
|
|
||||||
scc_ir_module_get_func(ctx->builder.ctx.module, func_ref);
|
|
||||||
Assert(func != nullptr);
|
|
||||||
scc_ir_builder_begin_bblock(&ctx->builder, "entry");
|
scc_ir_builder_begin_bblock(&ctx->builder, "entry");
|
||||||
|
|
||||||
scc_vec_foreach(decl->func.type->function.params, i) {
|
scc_vec_foreach(decl->func.type->function.params, i) {
|
||||||
scc_ast_decl_t *param =
|
scc_ast_decl_t *param =
|
||||||
scc_vec_at(decl->func.type->function.params, i);
|
scc_vec_at(decl->func.type->function.params, i);
|
||||||
|
scc_ast2ir_decl(ctx, param, false);
|
||||||
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 != nullptr);
|
|
||||||
param_node->name = param->name;
|
|
||||||
scc_hashtable_set(&ctx->ast2ir_cache, param,
|
|
||||||
(void *)(usize)param_node_ref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast2ir_stmt(ctx, decl->func.body);
|
scc_ast2ir_stmt(ctx, decl->func.body);
|
||||||
// FIXME need ret for none return or other default ret
|
// FIXME need ret for none return or other default ret
|
||||||
scc_ir_builder_ret_void(&ctx->builder);
|
scc_ir_builder_ret_void(&ctx->builder);
|
||||||
@@ -973,6 +967,23 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_DECL_PARAM: {
|
case SCC_AST_DECL_PARAM: {
|
||||||
|
if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN &&
|
||||||
|
decl->param.type->builtin.type == SCC_AST_BUILTIN_TYPE_VOID) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scc_ir_type_ref_t parma_type_ref =
|
||||||
|
scc_ast2ir_type(ctx, decl->param.type);
|
||||||
|
scc_ir_value_ref_t param_ref = scc_ir_builder_func_arg_ref(
|
||||||
|
&ctx->builder, parma_type_ref, decl->name, decl->param.param_idx);
|
||||||
|
|
||||||
|
if (!ctx->hint_using_value) {
|
||||||
|
scc_ir_value_ref_t val_ref = scc_ir_builder_alloca(
|
||||||
|
&ctx->builder, parma_type_ref, decl->name);
|
||||||
|
scc_ir_builder_store(&ctx->builder, val_ref, param_ref);
|
||||||
|
scc_hashtable_set(&ctx->ast2ir_cache, decl, (void *)(usize)val_ref);
|
||||||
|
} else {
|
||||||
|
Panic("using value is not supported");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_DECL_STRUCT:
|
case SCC_AST_DECL_STRUCT:
|
||||||
@@ -1022,8 +1033,10 @@ void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 scc_hash_node(const void *key) { return (u32)(usize)key; }
|
static u32 scc_hash_node(const void *key, void *userdata) {
|
||||||
static int scc_cmp_node(const void *key1, const void *key2) {
|
return (u32)(usize)key;
|
||||||
|
}
|
||||||
|
static int scc_cmp_node(const void *key1, const void *key2, void *userdata) {
|
||||||
return (u32)(usize)key1 - (u32)(usize)key2;
|
return (u32)(usize)key1 - (u32)(usize)key2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1032,9 +1045,10 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
|||||||
Assert(ctx != nullptr);
|
Assert(ctx != nullptr);
|
||||||
ctx->abi = abi;
|
ctx->abi = abi;
|
||||||
scc_ir_builder_init(&ctx->builder, cprog);
|
scc_ir_builder_init(&ctx->builder, cprog);
|
||||||
scc_hashtable_init(&ctx->ast2ir_cache, scc_hash_node, scc_cmp_node);
|
scc_hashtable_init(&ctx->ast2ir_cache, scc_hash_node, scc_cmp_node,
|
||||||
scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32,
|
nullptr);
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
scc_hashtable_cstr_init(&ctx->symtab);
|
||||||
|
ctx->hint_using_value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) {
|
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) {
|
||||||
|
|||||||
@@ -120,40 +120,9 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ir_type_ref_vec_t params = func_type->data.function.params;
|
|
||||||
// 释放借用,因为下面要调用 add_value(可能 realloc)
|
// 释放借用,因为下面要调用 add_value(可能 realloc)
|
||||||
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
SCC_IR_BUILDER_END_BORROW(builder); // func_type
|
||||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
||||||
|
|
||||||
// 预先分配所有参数值(临时数组,避免在循环中 push 到 func_ptr->params 时
|
|
||||||
// func_ptr 失效)
|
|
||||||
usize param_count = scc_vec_size(params);
|
|
||||||
scc_ir_value_ref_t *param_refs =
|
|
||||||
scc_malloc(sizeof(scc_ir_value_ref_t) * param_count);
|
|
||||||
|
|
||||||
for (usize i = 0; i < param_count; i++) {
|
|
||||||
scc_ir_type_ref_t param_type = scc_vec_at(params, i);
|
|
||||||
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] : nullptr;
|
|
||||||
param_node.data.arg_ref.idx = i;
|
|
||||||
scc_vec_init(param_node.used_by);
|
|
||||||
param_refs[i] =
|
|
||||||
scc_ir_module_add_value(GET_MODULE(builder), ¶m_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 重新借用 func_ptr 以添加参数到函数
|
|
||||||
SCC_IR_BUILDER_BEGIN_BORROW(
|
|
||||||
builder, func_ptr,
|
|
||||||
scc_ir_module_get_func(GET_MODULE(builder), func_ref));
|
|
||||||
for (usize i = 0; i < param_count; i++) {
|
|
||||||
scc_vec_push(func_ptr->params, param_refs[i]);
|
|
||||||
}
|
|
||||||
SCC_IR_BUILDER_END_BORROW(builder); // func_ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
|
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ static inline u32 scc_hash_mix(u32 seed, u32 value) {
|
|||||||
return (seed ^ value) * 16777619u;
|
return (seed ^ value) * 16777619u;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 hash_type(const void *_key) {
|
static u32 hash_type(const void *_key, void *userdata) {
|
||||||
const scc_ir_type_t *key = _key;
|
scc_ir_module_t *module = userdata;
|
||||||
|
const scc_ir_type_t *key =
|
||||||
|
_key == SCC_IR_REF_nullptr
|
||||||
|
? &scc_vec_at(module->types, 0)
|
||||||
|
: scc_ir_module_get_type(module, (usize)_key);
|
||||||
// 初始哈希:tag
|
// 初始哈希:tag
|
||||||
u32 hash = (u32)key->tag;
|
u32 hash = (u32)key->tag;
|
||||||
|
|
||||||
@@ -65,8 +69,16 @@ static u32 hash_type(const void *_key) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_type(const void *_key1, const void *_key2) {
|
static int cmp_type(const void *_key1, const void *_key2, void *userdata) {
|
||||||
const scc_ir_type_t *key1 = _key1, *key2 = _key2;
|
scc_ir_module_t *module = userdata;
|
||||||
|
const scc_ir_type_t *key1 =
|
||||||
|
_key1 == SCC_IR_REF_nullptr
|
||||||
|
? &scc_vec_at(module->types, 0)
|
||||||
|
: scc_ir_module_get_type(module, (usize)_key1),
|
||||||
|
*key2 =
|
||||||
|
_key2 == SCC_IR_REF_nullptr
|
||||||
|
? &scc_vec_at(module->types, 0)
|
||||||
|
: scc_ir_module_get_type(module, (usize)_key2);
|
||||||
Assert(key1 != nullptr && key2 != nullptr);
|
Assert(key1 != nullptr && key2 != nullptr);
|
||||||
if (key1->tag == SCC_IR_TYPE_unknown || key2->tag == SCC_IR_TYPE_unknown) {
|
if (key1->tag == SCC_IR_TYPE_unknown || key2->tag == SCC_IR_TYPE_unknown) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -123,12 +135,10 @@ static int cmp_type(const void *_key1, const void *_key2) {
|
|||||||
|
|
||||||
void scc_ir_ctx_init(scc_ir_ctx_t *ctx, scc_ir_module_t *module) {
|
void scc_ir_ctx_init(scc_ir_ctx_t *ctx, scc_ir_module_t *module) {
|
||||||
ctx->module = module;
|
ctx->module = module;
|
||||||
scc_hashtable_init(&ctx->type_uniquing, hash_type, cmp_type);
|
scc_hashtable_init(&ctx->type_uniquing, hash_type, cmp_type, module);
|
||||||
// scc_hashtable_init(&ctx->const_pool, /* 常量哈希函数 */,
|
// scc_hashtable_init(&ctx->const_pool, /* 常量哈希函数 */,
|
||||||
// /* 常量比较函数 */);
|
// /* 常量比较函数 */);
|
||||||
scc_hashtable_init(&ctx->func_decl_set,
|
scc_hashtable_cstr_init(&ctx->func_decl_set);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir_ctx_drop(scc_ir_ctx_t *ctx) {
|
void scc_ir_ctx_drop(scc_ir_ctx_t *ctx) {
|
||||||
@@ -140,15 +150,17 @@ 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,
|
scc_ir_type_ref_t scc_ir_ctx_get_type(scc_ir_ctx_t *ctx,
|
||||||
const scc_ir_type_t *type_desc) {
|
const scc_ir_type_t *type_desc) {
|
||||||
Assert(type_desc->tag != SCC_IR_TYPE_unknown);
|
Assert(type_desc->tag != SCC_IR_TYPE_unknown);
|
||||||
|
|
||||||
|
scc_vec_at(ctx->module->types, 0) = *type_desc;
|
||||||
// 先查哈希表
|
// 先查哈希表
|
||||||
void *found = scc_hashtable_get(&ctx->type_uniquing, (void *)type_desc);
|
void *found = scc_hashtable_get(&ctx->type_uniquing, (void *)(usize)0);
|
||||||
if (found) {
|
if (found) {
|
||||||
return (scc_ir_type_ref_t)(usize)found;
|
return (scc_ir_type_ref_t)(usize)found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 不存在,添加新类型
|
// 不存在,添加新类型
|
||||||
scc_ir_type_ref_t new_ref = scc_ir_module_add_type(ctx->module, type_desc);
|
scc_ir_type_ref_t new_ref = scc_ir_module_add_type(ctx->module, type_desc);
|
||||||
scc_hashtable_set(&ctx->type_uniquing, (void *)type_desc,
|
scc_hashtable_set(&ctx->type_uniquing, (void *)(usize)new_ref,
|
||||||
(void *)(usize)new_ref);
|
(void *)(usize)new_ref);
|
||||||
return new_ref;
|
return new_ref;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -658,7 +658,7 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref,
|
|||||||
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
|
scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref);
|
||||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||||
if (!func) {
|
if (!func) {
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "<invalid function>\n");
|
scc_tree_dump_append(ctx->dump_ctx, "<invalid function>");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s",
|
scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <ir_module.h>
|
#include <ir_module.h>
|
||||||
|
|
||||||
static u32 hash_key(const void *key) { return (u32)(usize)key; }
|
static u32 hash_key(const void *key, void *userdata) { return (u32)(usize)key; }
|
||||||
static int cmp_key(const void *key1, const void *key2) {
|
static int cmp_key(const void *key1, const void *key2, void *userdata) {
|
||||||
return (u32)(usize)key1 != (u32)(usize)key2;
|
return (u32)(usize)key1 != (u32)(usize)key2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10,11 +10,15 @@ void scc_ir_module_init(scc_ir_module_t *ctx) {
|
|||||||
scc_vec_init(ctx->types);
|
scc_vec_init(ctx->types);
|
||||||
scc_vec_init(ctx->bblocks);
|
scc_vec_init(ctx->bblocks);
|
||||||
scc_vec_init(ctx->funcs);
|
scc_vec_init(ctx->funcs);
|
||||||
scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key);
|
scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key, nullptr);
|
||||||
scc_hashtable_init(&ctx->uid2type, hash_key, cmp_key);
|
scc_hashtable_init(&ctx->uid2type, hash_key, cmp_key, nullptr);
|
||||||
scc_hashtable_init(&ctx->uid2bblock, hash_key, cmp_key);
|
scc_hashtable_init(&ctx->uid2bblock, hash_key, cmp_key, nullptr);
|
||||||
scc_hashtable_init(&ctx->uid2func, hash_key, cmp_key);
|
scc_hashtable_init(&ctx->uid2func, hash_key, cmp_key, nullptr);
|
||||||
// 预留UID 0 作为无效引用
|
// 预留UID 0 作为无效引用
|
||||||
|
scc_vec_push(ctx->values, (scc_ir_value_t){0});
|
||||||
|
scc_vec_push(ctx->types, (scc_ir_type_t){0});
|
||||||
|
scc_vec_push(ctx->bblocks, (scc_ir_bblock_t){0});
|
||||||
|
scc_vec_push(ctx->funcs, (scc_ir_func_t){0});
|
||||||
ctx->value_uid = 1;
|
ctx->value_uid = 1;
|
||||||
ctx->type_uid = 1;
|
ctx->type_uid = 1;
|
||||||
ctx->bblock_uid = 1;
|
ctx->bblock_uid = 1;
|
||||||
@@ -23,7 +27,7 @@ void scc_ir_module_init(scc_ir_module_t *ctx) {
|
|||||||
|
|
||||||
void scc_ir_module_drop(scc_ir_module_t *ctx) {
|
void scc_ir_module_drop(scc_ir_module_t *ctx) {
|
||||||
// 释放所有实体的内部内存
|
// 释放所有实体的内部内存
|
||||||
for (usize i = 0; i < ctx->values.size; i++) {
|
for (usize i = 1; i < ctx->values.size; i++) {
|
||||||
scc_ir_value_t *node = &ctx->values.data[i];
|
scc_ir_value_t *node = &ctx->values.data[i];
|
||||||
scc_vec_free(node->used_by);
|
scc_vec_free(node->used_by);
|
||||||
if (node->tag == SCC_IR_VALUE_TAG_CALL) {
|
if (node->tag == SCC_IR_VALUE_TAG_CALL) {
|
||||||
@@ -31,19 +35,19 @@ void scc_ir_module_drop(scc_ir_module_t *ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < ctx->types.size; i++) {
|
for (usize i = 1; i < ctx->types.size; i++) {
|
||||||
scc_ir_type_t *type = &ctx->types.data[i];
|
scc_ir_type_t *type = &ctx->types.data[i];
|
||||||
if (type->tag == SCC_IR_TYPE_FUNC) {
|
if (type->tag == SCC_IR_TYPE_FUNC) {
|
||||||
scc_vec_free(type->data.function.params);
|
scc_vec_free(type->data.function.params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < ctx->bblocks.size; i++) {
|
for (usize i = 1; i < ctx->bblocks.size; i++) {
|
||||||
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
|
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
|
||||||
scc_vec_free(bblock->instrs);
|
scc_vec_free(bblock->instrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (usize i = 0; i < ctx->funcs.size; i++) {
|
for (usize i = 1; i < ctx->funcs.size; i++) {
|
||||||
scc_ir_func_t *func = &ctx->funcs.data[i];
|
scc_ir_func_t *func = &ctx->funcs.data[i];
|
||||||
scc_vec_free(func->params);
|
scc_vec_free(func->params);
|
||||||
scc_vec_free(func->bblocks);
|
scc_vec_free(func->bblocks);
|
||||||
@@ -64,11 +68,11 @@ void scc_ir_module_drop(scc_ir_module_t *ctx) {
|
|||||||
do { \
|
do { \
|
||||||
/* 分配新UID */ \
|
/* 分配新UID */ \
|
||||||
unsigned new_uid = (ctx)->uid++; \
|
unsigned new_uid = (ctx)->uid++; \
|
||||||
/* 添加到向量 */ \
|
|
||||||
scc_vec_push((vec), *(data)); \
|
|
||||||
/* 添加到哈希表 */ \
|
/* 添加到哈希表 */ \
|
||||||
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
|
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
|
||||||
(void *)(usize)(scc_vec_size(vec) - 1)); \
|
(void *)(usize)(scc_vec_size(vec))); \
|
||||||
|
/* 添加到向量 */ \
|
||||||
|
scc_vec_push((vec), *(data)); \
|
||||||
return new_uid; \
|
return new_uid; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "ir2mcode"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = []
|
|
||||||
description = ""
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
{ name = "scc_utils", path = "../../runtime/scc_utils" },
|
|
||||||
{ name = "scc_ir", path = "../ir" },
|
|
||||||
{ name = "scc_mcode", path = "../mcode" },
|
|
||||||
{ name = "sccf", path = "../sccf" },
|
|
||||||
|
|
||||||
{ name = "lexer", path = "../lexer" },
|
|
||||||
{ name = "pproc", path = "../pproc" },
|
|
||||||
{ name = "parser", path = "../parser" },
|
|
||||||
{ name = "ast", path = "../ast" },
|
|
||||||
{ name = "ast2ir", path = "../ast2ir" },
|
|
||||||
{ name = "sccf2target", path = "../target/sccf2target" },
|
|
||||||
]
|
|
||||||
# features = {}
|
|
||||||
# default_features = []
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
#ifndef __SCC_FRAME_ALLOC_H__
|
|
||||||
#define __SCC_FRAME_ALLOC_H__
|
|
||||||
|
|
||||||
#include <scc_ir.h>
|
|
||||||
|
|
||||||
typedef struct scc_frame_alloc_ops scc_frame_alloc_ops_t;
|
|
||||||
struct scc_frame_alloc_ops {
|
|
||||||
/// maybe have direct function to new
|
|
||||||
scc_frame_alloc_ops_t *(*new)(scc_ir_func_t *func);
|
|
||||||
int (*drop)(scc_frame_alloc_ops_t *alloc);
|
|
||||||
|
|
||||||
int (*alloc_spill_slot)(scc_frame_alloc_ops_t *frame, int size, int align);
|
|
||||||
int (*alloc_local_slot)(scc_frame_alloc_ops_t *frame, int size, int align,
|
|
||||||
const char *name);
|
|
||||||
|
|
||||||
void (*finalize)(scc_frame_alloc_ops_t *frame);
|
|
||||||
int (*get_slot_offset)(scc_frame_alloc_ops_t *frame, int slot_id);
|
|
||||||
int (*get_frame_size)(scc_frame_alloc_ops_t *frame);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
#ifndef __SCC_REG_ALLOC_H__
|
|
||||||
#define __SCC_REG_ALLOC_H__
|
|
||||||
|
|
||||||
#include "frame_alloc.h"
|
|
||||||
#include <scc_core.h>
|
|
||||||
#include <scc_ir.h>
|
|
||||||
#include <scc_utils.h>
|
|
||||||
|
|
||||||
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_STACK_ADDR, ///< 栈地址(如 alloc 节点)
|
|
||||||
SCC_REG_KIND_IMM, ///< 整数立即数
|
|
||||||
SCC_REG_KIND_IMM_FP, ///< 浮点数常量
|
|
||||||
} scc_reg_kind_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
scc_reg_kind_t kind;
|
|
||||||
union {
|
|
||||||
usize data;
|
|
||||||
int slot_idx;
|
|
||||||
int gpr_idx;
|
|
||||||
int fpr_idx;
|
|
||||||
} data;
|
|
||||||
} scc_reg_loc_t;
|
|
||||||
typedef SCC_VEC(scc_reg_loc_t) scc_reg_loc_vec_t;
|
|
||||||
|
|
||||||
struct scc_reg_alloc;
|
|
||||||
typedef struct scc_reg_alloc scc_reg_alloc_t;
|
|
||||||
typedef void (*scc_reg_alloc_func_t)(scc_reg_alloc_t *ctx, scc_ir_func_t *func,
|
|
||||||
scc_frame_alloc_ops_t *frame_alloc);
|
|
||||||
|
|
||||||
typedef struct scc_reg_alloc {
|
|
||||||
scc_frame_alloc_ops_t *frame_alloc;
|
|
||||||
scc_ir_module_t *ir_module; ///< IR存储节点
|
|
||||||
scc_hashtable_t node2loc; ///< 输出结果哈希表
|
|
||||||
scc_reg_loc_vec_t loc_vec;
|
|
||||||
scc_reg_alloc_func_t reg_alloc_func;
|
|
||||||
} scc_reg_alloc_t;
|
|
||||||
|
|
||||||
void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t strategy,
|
|
||||||
scc_ir_module_t *ir_module);
|
|
||||||
static inline scc_hashtable_t *
|
|
||||||
scc_reg_alloc_run(scc_reg_alloc_t *ctx, scc_ir_func_t *func,
|
|
||||||
const scc_frame_alloc_ops_t *frame_alloc) {
|
|
||||||
if (ctx->frame_alloc != nullptr) {
|
|
||||||
ctx->frame_alloc->drop(ctx->frame_alloc);
|
|
||||||
ctx->frame_alloc = nullptr;
|
|
||||||
}
|
|
||||||
Assert(ctx->frame_alloc == nullptr);
|
|
||||||
ctx->frame_alloc = frame_alloc->new(func);
|
|
||||||
Assert(ctx->frame_alloc != nullptr);
|
|
||||||
ctx->reg_alloc_func(ctx, func, ctx->frame_alloc);
|
|
||||||
ctx->frame_alloc->finalize(ctx->frame_alloc);
|
|
||||||
return &ctx->node2loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline usize scc_reg_stack_size(scc_reg_alloc_t *ctx) {
|
|
||||||
return ctx->frame_alloc->get_frame_size(ctx->frame_alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int scc_reg_stack_offset(scc_reg_alloc_t *ctx,
|
|
||||||
scc_reg_loc_t *loc) {
|
|
||||||
Assert(loc->kind == SCC_REG_KIND_STACK ||
|
|
||||||
loc->kind == SCC_REG_KIND_STACK_ADDR);
|
|
||||||
return ctx->frame_alloc->get_slot_offset(ctx->frame_alloc,
|
|
||||||
loc->data.slot_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx,
|
|
||||||
scc_ir_func_t *func,
|
|
||||||
scc_frame_alloc_ops_t *frame_alloc);
|
|
||||||
|
|
||||||
#endif /* __SCC_REG_ALLOC_H__ */
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#ifndef __SCC_IR2MCODE_H__
|
|
||||||
#define __SCC_IR2MCODE_H__
|
|
||||||
|
|
||||||
#include "reg_alloc.h"
|
|
||||||
#include <scc_core.h>
|
|
||||||
#include <scc_ir.h>
|
|
||||||
#include <scc_mcode.h>
|
|
||||||
#include <sccf_builder.h>
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
scc_ir_cprog_t *cprog;
|
|
||||||
sccf_builder_t *builder;
|
|
||||||
scc_mcode_t sect_mcode;
|
|
||||||
sccf_sect_data_t sect_data;
|
|
||||||
|
|
||||||
// FIXME
|
|
||||||
usize stack_size;
|
|
||||||
scc_reg_alloc_t reg_alloc;
|
|
||||||
scc_hashtable_t *noderef2regloc;
|
|
||||||
} scc_ir2mcode_ctx_t;
|
|
||||||
|
|
||||||
// amd64
|
|
||||||
|
|
||||||
void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog,
|
|
||||||
sccf_builder_t *builder, scc_mcode_arch_t arch);
|
|
||||||
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx);
|
|
||||||
|
|
||||||
void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx);
|
|
||||||
|
|
||||||
#endif /* __SCC_IR2MCODE_H__ */
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
|
|
||||||
#include <scc_ir.h>
|
|
||||||
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type);
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
#include <frame_alloc.h>
|
|
||||||
#include <scc_utils.h>
|
|
||||||
#include <type_manager.h>
|
|
||||||
|
|
||||||
static const int WIN64_DEFAULT_ALIGN = 8;
|
|
||||||
static const int WIN64_STACK_ALIGN = 16;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int size;
|
|
||||||
int align;
|
|
||||||
int slot_id;
|
|
||||||
int offset; // 最终计算的偏移(负值)
|
|
||||||
} win64_slot_t;
|
|
||||||
|
|
||||||
typedef SCC_VEC(win64_slot_t) win64_slot_vec_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
scc_frame_alloc_ops_t base;
|
|
||||||
scc_ir_func_t *func;
|
|
||||||
win64_slot_vec_t slots; // 所有已分配的槽位
|
|
||||||
scc_hashtable_t offset_cache; // slot_id -> offset
|
|
||||||
int stack_size; // 最终对齐后的栈帧大小
|
|
||||||
int finalized; // 是否已调用 finalize
|
|
||||||
} win64_alloc_t;
|
|
||||||
|
|
||||||
/* ---------- 辅助函数 ---------- */
|
|
||||||
static u32 hash_ptr(const void *key) { return (u32)(uintptr_t)key; }
|
|
||||||
|
|
||||||
static int cmp_ptr(const void *a, const void *b) {
|
|
||||||
return (uintptr_t)a != (uintptr_t)b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 槽位分配 ---------- */
|
|
||||||
static int win64_alloc_slot_common(win64_alloc_t *self, int size, int align) {
|
|
||||||
if (self->finalized) {
|
|
||||||
Panic("frame_alloc: cannot allocate after finalize");
|
|
||||||
}
|
|
||||||
win64_slot_t slot;
|
|
||||||
slot.size = (size <= 0) ? WIN64_DEFAULT_ALIGN : size;
|
|
||||||
slot.align = (align <= 0) ? WIN64_DEFAULT_ALIGN : align;
|
|
||||||
// 对齐不能小于自然对齐
|
|
||||||
if (slot.align < 1)
|
|
||||||
slot.align = 1;
|
|
||||||
slot.slot_id = (int)scc_vec_size(self->slots);
|
|
||||||
slot.offset = 0; // 暂未计算
|
|
||||||
scc_vec_push(self->slots, slot);
|
|
||||||
return slot.slot_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int win64_alloc_spill_slot(scc_frame_alloc_ops_t *ops, int size,
|
|
||||||
int align) {
|
|
||||||
win64_alloc_t *self = (win64_alloc_t *)ops;
|
|
||||||
return win64_alloc_slot_common(self, size, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int win64_alloc_local_slot(scc_frame_alloc_ops_t *ops, int size,
|
|
||||||
int align, const char *name) {
|
|
||||||
(void)name; // 本实现不记录名称
|
|
||||||
return win64_alloc_spill_slot(ops, size, align);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 最终布局计算 ---------- */
|
|
||||||
static void win64_finalize(scc_frame_alloc_ops_t *ops) {
|
|
||||||
win64_alloc_t *self = (win64_alloc_t *)ops;
|
|
||||||
if (self->finalized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int current_offset = -WIN64_DEFAULT_ALIGN; // 从 -8 开始
|
|
||||||
|
|
||||||
for (usize i = 0; i < scc_vec_size(self->slots); i++) {
|
|
||||||
win64_slot_t *slot = &scc_vec_at(self->slots, i);
|
|
||||||
int align = slot->align;
|
|
||||||
|
|
||||||
// 向下对齐到 align 的倍数(current_offset 为负数)
|
|
||||||
int rem = ((-current_offset) % align);
|
|
||||||
if (rem != 0) {
|
|
||||||
current_offset -= (align - rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
current_offset -= slot->size;
|
|
||||||
slot->offset = current_offset;
|
|
||||||
scc_hashtable_set(&self->offset_cache, (void *)(intptr_t)slot->slot_id,
|
|
||||||
(void *)(intptr_t)slot->offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int total_size = -current_offset + 32; // 加上影子空间
|
|
||||||
// 16 字节栈对齐
|
|
||||||
int aligned =
|
|
||||||
(total_size + WIN64_STACK_ALIGN - 1) & ~(WIN64_STACK_ALIGN - 1);
|
|
||||||
self->stack_size = aligned;
|
|
||||||
self->finalized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int win64_get_slot_offset(scc_frame_alloc_ops_t *ops, int slot_id) {
|
|
||||||
win64_alloc_t *self = (win64_alloc_t *)ops;
|
|
||||||
if (!self->finalized) {
|
|
||||||
Panic("frame_alloc: get_slot_offset before finalize");
|
|
||||||
}
|
|
||||||
void *offset =
|
|
||||||
scc_hashtable_get(&self->offset_cache, (void *)(intptr_t)slot_id);
|
|
||||||
if (!offset) {
|
|
||||||
Panic("frame_alloc: invalid slot_id %d", slot_id);
|
|
||||||
}
|
|
||||||
return (int)(intptr_t)offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int win64_get_frame_size(scc_frame_alloc_ops_t *ops) {
|
|
||||||
win64_alloc_t *self = (win64_alloc_t *)ops;
|
|
||||||
if (!self->finalized) {
|
|
||||||
Panic("frame_alloc: get_frame_size before finalize");
|
|
||||||
}
|
|
||||||
return self->stack_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 析构 ---------- */
|
|
||||||
static int win64_drop(scc_frame_alloc_ops_t *ops) {
|
|
||||||
win64_alloc_t *self = (win64_alloc_t *)ops;
|
|
||||||
scc_vec_free(self->slots);
|
|
||||||
scc_hashtable_drop(&self->offset_cache);
|
|
||||||
scc_free(self);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 构造函数 ---------- */
|
|
||||||
scc_frame_alloc_ops_t *scc_frame_alloc_win64_new(scc_ir_func_t *func) {
|
|
||||||
win64_alloc_t *self = scc_malloc(sizeof(win64_alloc_t));
|
|
||||||
scc_memset(self, 0, sizeof(*self));
|
|
||||||
|
|
||||||
self->base.alloc_spill_slot = win64_alloc_spill_slot;
|
|
||||||
self->base.alloc_local_slot = win64_alloc_local_slot;
|
|
||||||
self->base.finalize = win64_finalize;
|
|
||||||
self->base.get_slot_offset = win64_get_slot_offset;
|
|
||||||
self->base.get_frame_size = win64_get_frame_size;
|
|
||||||
self->base.drop = win64_drop;
|
|
||||||
|
|
||||||
self->func = func;
|
|
||||||
self->finalized = 0;
|
|
||||||
self->stack_size = 0;
|
|
||||||
|
|
||||||
scc_vec_init(self->slots);
|
|
||||||
scc_hashtable_init(&self->offset_cache, hash_ptr, cmp_ptr);
|
|
||||||
|
|
||||||
return &self->base;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 提供一个全局的 ops 模板(可选,便于外部使用) */
|
|
||||||
static const scc_frame_alloc_ops_t win64_ops_template = {
|
|
||||||
.new = scc_frame_alloc_win64_new,
|
|
||||||
.drop = win64_drop,
|
|
||||||
.alloc_spill_slot = win64_alloc_spill_slot,
|
|
||||||
.alloc_local_slot = win64_alloc_local_slot,
|
|
||||||
.finalize = win64_finalize,
|
|
||||||
.get_slot_offset = win64_get_slot_offset,
|
|
||||||
.get_frame_size = win64_get_frame_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
const scc_frame_alloc_ops_t *scc_frame_alloc_win64_ops(void) {
|
|
||||||
return &win64_ops_template;
|
|
||||||
}
|
|
||||||
@@ -1,786 +0,0 @@
|
|||||||
#include <amd64/scc_amd64.h>
|
|
||||||
#include <amd64/scc_amd64_abi.h>
|
|
||||||
#include <reg_alloc.h>
|
|
||||||
#include <scc_ir2mcode.h>
|
|
||||||
#include <type_manager.h>
|
|
||||||
|
|
||||||
#define GET_MODULE(ctx) (&(ctx->cprog->module))
|
|
||||||
|
|
||||||
static bool scc_type_is_signed(scc_ir_type_t *type) {
|
|
||||||
return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 ||
|
|
||||||
type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
|
||||||
scc_ir_value_ref_t node_ref) {
|
|
||||||
Assert(ctx != nullptr && loc != nullptr);
|
|
||||||
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
|
||||||
if (value == nullptr) {
|
|
||||||
LOG_FATAL("invalid value ref");
|
|
||||||
UNREACHABLE();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
usize idx = 0;
|
|
||||||
switch (value->tag) {
|
|
||||||
case SCC_IR_VALUE_TAG_CONST_INT:
|
|
||||||
scc_ir_type_t *type =
|
|
||||||
scc_ir_module_get_type(GET_MODULE(ctx), value->type);
|
|
||||||
Assert(type != 0);
|
|
||||||
switch (type->tag) {
|
|
||||||
case SCC_IR_TYPE_u8:
|
|
||||||
case SCC_IR_TYPE_i8:
|
|
||||||
*loc = (scc_reg_loc_t){
|
|
||||||
.kind = SCC_REG_KIND_IMM,
|
|
||||||
.data.data = (usize)value->data.const_int.int8,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case SCC_IR_TYPE_u16:
|
|
||||||
case SCC_IR_TYPE_i16:
|
|
||||||
*loc = (scc_reg_loc_t){
|
|
||||||
.kind = SCC_REG_KIND_IMM,
|
|
||||||
.data.data = (usize)value->data.const_int.int16,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case SCC_IR_TYPE_u32:
|
|
||||||
case SCC_IR_TYPE_i32:
|
|
||||||
*loc = (scc_reg_loc_t){
|
|
||||||
.kind = SCC_REG_KIND_IMM,
|
|
||||||
.data.data = (usize)value->data.const_int.int32,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case SCC_IR_TYPE_u64:
|
|
||||||
case SCC_IR_TYPE_i64:
|
|
||||||
*loc = (scc_reg_loc_t){
|
|
||||||
.kind = SCC_REG_KIND_IMM,
|
|
||||||
.data.data = (usize)value->data.const_int.int64,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
case SCC_IR_VALUE_TAG_CONST_UINT:
|
|
||||||
case SCC_IR_VALUE_TAG_CONST_FLOAT:
|
|
||||||
TODO();
|
|
||||||
break;
|
|
||||||
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
|
|
||||||
TODO();
|
|
||||||
break;
|
|
||||||
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
|
|
||||||
case SCC_IR_VALUE_TAG_ALLOC:
|
|
||||||
default:
|
|
||||||
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
|
|
||||||
(void *)(usize)node_ref);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.loc_vec));
|
|
||||||
*loc = scc_vec_at(ctx->reg_alloc.loc_vec, idx - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void load_value_to_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
|
||||||
int reg) {
|
|
||||||
scc_mcode_t *mcode = &ctx->sect_mcode;
|
|
||||||
switch (loc->kind) {
|
|
||||||
case SCC_REG_KIND_GPR:
|
|
||||||
if (loc->data.gpr_idx != reg) {
|
|
||||||
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->data.gpr_idx);
|
|
||||||
} else {
|
|
||||||
TODO();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_STACK:
|
|
||||||
scc_mcode_amd64_mov_r64_m64_disp32(
|
|
||||||
mcode, reg, SCC_AMD64_RBP,
|
|
||||||
scc_reg_stack_offset(&ctx->reg_alloc, loc));
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_STACK_ADDR:
|
|
||||||
// 将栈地址加载到寄存器(取地址)
|
|
||||||
scc_mcode_amd64_lea_r64_m64_disp32(
|
|
||||||
mcode, reg, SCC_AMD64_RBP,
|
|
||||||
scc_reg_stack_offset(&ctx->reg_alloc, loc));
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_IMM:
|
|
||||||
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->data.data); // 或 imm32
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_FATAL("unsupported location");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void store_value_from_reg(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
|
||||||
int reg) {
|
|
||||||
scc_mcode_t *mcode = &ctx->sect_mcode;
|
|
||||||
switch (loc->kind) {
|
|
||||||
case SCC_REG_KIND_GPR:
|
|
||||||
if (loc->data.gpr_idx != reg) {
|
|
||||||
scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_STACK:
|
|
||||||
scc_mcode_amd64_mov_m64_disp32_r64(
|
|
||||||
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
|
|
||||||
reg);
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_STACK_ADDR:
|
|
||||||
// 将寄存器的值存储到栈地址
|
|
||||||
scc_mcode_amd64_mov_m64_disp32_r64(
|
|
||||||
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
|
|
||||||
reg);
|
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_IMM:
|
|
||||||
LOG_FATAL("cannot store to immediate");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Panic("unsupported location %d", loc->kind);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 临时存储待修补条目
|
|
||||||
typedef struct patch {
|
|
||||||
usize pos;
|
|
||||||
usize target_bb_ref;
|
|
||||||
} patch_t;
|
|
||||||
typedef SCC_VEC(patch_t) patch_vec_t;
|
|
||||||
|
|
||||||
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
||||||
patch_vec_t *patches) {
|
|
||||||
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
|
||||||
if (value == nullptr) {
|
|
||||||
LOG_ERROR("invalid value ref");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (value->tag) {
|
|
||||||
case SCC_IR_VALUE_TAG_BUILTIN: {
|
|
||||||
scc_ir_builtin_t *builtin = &value->data.builtin;
|
|
||||||
switch (builtin->tag) {
|
|
||||||
case SCC_IR_BUILTIN_TAG_MEMCPY: {
|
|
||||||
// 1. 获取操作数的位置
|
|
||||||
scc_reg_loc_t dest_loc, src_loc, size_loc;
|
|
||||||
parse_location(ctx, &dest_loc, builtin->func.memcpy.dest);
|
|
||||||
parse_location(ctx, &src_loc, builtin->func.memcpy.src);
|
|
||||||
scc_ir_value_t *const_value = scc_ir_module_get_value(
|
|
||||||
GET_MODULE(ctx), builtin->func.memcpy.size);
|
|
||||||
Assert(const_value->tag == SCC_IR_VALUE_TAG_CONST_INT);
|
|
||||||
size_loc.kind = SCC_REG_KIND_IMM;
|
|
||||||
size_loc.data.data = const_value->data.const_int.int64;
|
|
||||||
|
|
||||||
// 2. 将 dest 地址加载到 RDI(rep movsb 目标)
|
|
||||||
load_value_to_reg(ctx, &dest_loc, SCC_AMD64_RDI);
|
|
||||||
// 3. 将 src 地址加载到 RSI
|
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RSI);
|
|
||||||
// 4. 将长度加载到 RCX
|
|
||||||
load_value_to_reg(ctx, &size_loc, SCC_AMD64_RCX);
|
|
||||||
|
|
||||||
// 5. 如果长度可能为 0,可以跳过,但 rep movsb 处理 0
|
|
||||||
// 也没问题,只是多一次指令。 生成 rep movsb 指令(字节复制)
|
|
||||||
// 需要使用 REX.W 前缀保证 64 位操作,但 rep movsb 本身不需要 REX.W
|
|
||||||
// 为了复制字节,使用 rep movsb (0xF3 0xA4)
|
|
||||||
scc_mcode_add_u8(&ctx->sect_mcode, 0xF3); // rep prefix
|
|
||||||
scc_mcode_add_u8(&ctx->sect_mcode, 0xA4); // movsb
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
Panic("unsupported builtin");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SCC_IR_VALUE_TAG_CONV: ///< 类型转换
|
|
||||||
LOG_FATAL("Unsupported value type: %d", value->tag);
|
|
||||||
break;
|
|
||||||
///< 函数参数引用
|
|
||||||
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
|
|
||||||
///< ABI
|
|
||||||
break;
|
|
||||||
case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用
|
|
||||||
break;
|
|
||||||
case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack)
|
|
||||||
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss
|
|
||||||
break;
|
|
||||||
///< 加载数据
|
|
||||||
case SCC_IR_VALUE_TAG_LOAD: {
|
|
||||||
// value->data.load.target
|
|
||||||
scc_reg_loc_t from;
|
|
||||||
scc_reg_loc_t to;
|
|
||||||
parse_location(ctx, &from, value->data.load.target);
|
|
||||||
parse_location(ctx, &to, node_ref);
|
|
||||||
|
|
||||||
load_value_to_reg(ctx, &from, SCC_AMD64_RCX);
|
|
||||||
// 获取基类型宽度
|
|
||||||
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
|
|
||||||
GET_MODULE(ctx), value->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_ir2mcode_type_width(GET_MODULE(ctx), 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 {
|
|
||||||
LOG_WARN("unsupported type width: %d", width);
|
|
||||||
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
}
|
|
||||||
// 存储结果
|
|
||||||
store_value_from_reg(ctx, &to, SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 存储数据
|
|
||||||
case SCC_IR_VALUE_TAG_STORE: {
|
|
||||||
scc_reg_loc_t val_loc, addr_loc;
|
|
||||||
parse_location(ctx, &val_loc, value->data.store.value);
|
|
||||||
parse_location(ctx, &addr_loc, value->data.store.target);
|
|
||||||
|
|
||||||
// 将值加载到 RAX
|
|
||||||
load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX);
|
|
||||||
// 将目标地址加载到 RCX
|
|
||||||
load_value_to_reg(ctx, &addr_loc, SCC_AMD64_RCX);
|
|
||||||
|
|
||||||
// 获取目标指针的基类型宽度
|
|
||||||
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
|
|
||||||
GET_MODULE(ctx), value->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_ir2mcode_type_width(GET_MODULE(ctx), 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_VALUE_TAG_GET_ELEM_PTR: {
|
|
||||||
scc_reg_loc_t loc_res;
|
|
||||||
parse_location(ctx, &loc_res, node_ref);
|
|
||||||
|
|
||||||
scc_ir_value_t *src_addr = scc_ir_module_get_value(
|
|
||||||
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
|
|
||||||
Assert(src_addr != nullptr);
|
|
||||||
if (value->data.get_elem_ptr.index == 0) {
|
|
||||||
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
|
||||||
// 全局变量:RIP相对寻址
|
|
||||||
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_CODE,
|
|
||||||
.sym_idx = sym_idx,
|
|
||||||
});
|
|
||||||
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
|
||||||
// 栈上变量:地址为 rbp - offset
|
|
||||||
scc_reg_loc_t src_loc;
|
|
||||||
parse_location(ctx, &src_loc,
|
|
||||||
value->data.get_elem_ptr.src_addr);
|
|
||||||
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
|
||||||
} else {
|
|
||||||
// 其他情况(如链式getptr):源地址值已经存储在某个位置,直接加载到
|
|
||||||
// RAX
|
|
||||||
scc_reg_loc_t src_loc;
|
|
||||||
parse_location(ctx, &src_loc,
|
|
||||||
value->data.get_elem_ptr.src_addr);
|
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// TODO
|
|
||||||
// parse_value(ctx, value->data.get_elem_ptr.index, patches);
|
|
||||||
|
|
||||||
scc_reg_loc_t src_loc;
|
|
||||||
scc_reg_loc_t idx_loc;
|
|
||||||
parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr);
|
|
||||||
parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index);
|
|
||||||
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
|
||||||
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
|
||||||
load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX);
|
|
||||||
|
|
||||||
// 获取 src_addr 所指向的类型的元素大小
|
|
||||||
scc_ir_type_t *ptr_type = scc_ir_module_get_type_by_value(
|
|
||||||
GET_MODULE(ctx), value->data.get_elem_ptr.src_addr);
|
|
||||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
|
||||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
|
||||||
scc_ir_type_t ir_type = *base_type;
|
|
||||||
if (ir_type.tag == SCC_IR_TYPE_ARRAY) {
|
|
||||||
ir_type.tag = SCC_IR_TYPE_PTR;
|
|
||||||
}
|
|
||||||
int elem_size = scc_ir2mcode_type_width(GET_MODULE(ctx), &ir_type);
|
|
||||||
// 然后生成 LEA 时使用 scale = elem_size
|
|
||||||
scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX, SCC_AMD64_RDX,
|
|
||||||
elem_size, 0);
|
|
||||||
}
|
|
||||||
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 二元运算
|
|
||||||
case SCC_IR_VALUE_TAG_OP: {
|
|
||||||
scc_reg_loc_t loc_lhs;
|
|
||||||
parse_location(ctx, &loc_lhs, value->data.op.lhs);
|
|
||||||
scc_reg_loc_t loc_rhs;
|
|
||||||
parse_location(ctx, &loc_rhs, value->data.op.rhs);
|
|
||||||
scc_reg_loc_t loc_res;
|
|
||||||
parse_location(ctx, &loc_res, node_ref);
|
|
||||||
|
|
||||||
// 将左操作数加载到 RAX(临时结果寄存器)
|
|
||||||
load_value_to_reg(ctx, &loc_lhs, SCC_AMD64_RAX);
|
|
||||||
// 将右操作数加载到 RCX
|
|
||||||
load_value_to_reg(ctx, &loc_rhs, SCC_AMD64_RCX);
|
|
||||||
switch (value->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);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_SUB:
|
|
||||||
scc_mcode_amd64_sub_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_MUL:
|
|
||||||
scc_mcode_amd64_mul_r64(&ctx->sect_mcode, SCC_AMD64_RCX);
|
|
||||||
break;
|
|
||||||
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);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_NE,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_EQ:
|
|
||||||
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_E,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_GT:
|
|
||||||
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_G,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_LT:
|
|
||||||
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_L,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_GE:
|
|
||||||
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_GE,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
case SCC_IR_OP_LE:
|
|
||||||
scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RCX);
|
|
||||||
scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_LE,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG_FATAL("unknown op: %d", value->data.op.op);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// 将 RAX 中的结果存储到 res 位置
|
|
||||||
store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 有条件分支
|
|
||||||
case SCC_IR_VALUE_TAG_BRANCH: {
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
parse_location(ctx, &loc, value->data.branch.cond);
|
|
||||||
// (void)loc;
|
|
||||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
|
|
||||||
scc_mcode_amd64_cmp_r64_imm32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
|
|
||||||
|
|
||||||
scc_mcode_amd64_jcc_rel32(&ctx->sect_mcode, SCC_AMD64_COND_NE, 0);
|
|
||||||
patch_t patch_true = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
|
|
||||||
.target_bb_ref =
|
|
||||||
(usize)value->data.branch.true_bblock};
|
|
||||||
scc_vec_push(*patches, patch_true);
|
|
||||||
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
|
|
||||||
patch_t patch_false = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
|
|
||||||
.target_bb_ref =
|
|
||||||
(usize)value->data.branch.false_bblock};
|
|
||||||
scc_vec_push(*patches, patch_false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 无条件跳转
|
|
||||||
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, .target_bb_ref = (usize)value->data.jump.target_bblock};
|
|
||||||
scc_vec_push(*patches, patch);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 调用函数
|
|
||||||
case SCC_IR_VALUE_TAG_CALL: {
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
usize nargs = scc_vec_size(value->data.call.args);
|
|
||||||
// 影子空间 32 字节 + 每个额外参数 8 字节(按 8 字节对齐)
|
|
||||||
usize stack_args_count = (nargs > 4) ? (nargs - 4) : 0;
|
|
||||||
usize stack_args_size = stack_args_count * 8;
|
|
||||||
usize total_stack_alloc = 32 + stack_args_size;
|
|
||||||
|
|
||||||
// 调整栈指针(保持 16 字节对齐)
|
|
||||||
if (total_stack_alloc > 0) {
|
|
||||||
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理寄存器参数(前 4 个)
|
|
||||||
for (usize i = 0; i < nargs && i < 4; i++) {
|
|
||||||
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
|
|
||||||
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
|
|
||||||
SCC_AMD64_R9};
|
|
||||||
load_value_to_reg(ctx, &loc, reg[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理栈参数(第 5 个及以后)
|
|
||||||
// 从右向左依次写入栈(即最后一个参数放在最高地址)
|
|
||||||
for (usize i = 4; i < nargs; i++) {
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
|
|
||||||
// 加载到临时寄存器(如 RAX)
|
|
||||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
|
|
||||||
// 计算栈偏移:影子空间(32) + (i-4)*8
|
|
||||||
int offset = 32 + (i - 4) * 8;
|
|
||||||
scc_mcode_amd64_mov_m64_disp32_r64(&ctx->sect_mcode, SCC_AMD64_RSP,
|
|
||||||
offset, SCC_AMD64_RAX);
|
|
||||||
}
|
|
||||||
|
|
||||||
scc_ir_func_t *func =
|
|
||||||
scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
|
|
||||||
if (!func) {
|
|
||||||
LOG_ERROR("invalid function reference");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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(
|
|
||||||
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_CODE,
|
|
||||||
.sym_idx = sym_idx,
|
|
||||||
});
|
|
||||||
// 恢复栈指针
|
|
||||||
if (total_stack_alloc > 0) {
|
|
||||||
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, total_stack_alloc);
|
|
||||||
}
|
|
||||||
// 处理返回值
|
|
||||||
scc_ir_type_t *func_type =
|
|
||||||
scc_ir_module_get_type(GET_MODULE(ctx), func->type);
|
|
||||||
Assert(func_type);
|
|
||||||
scc_ir_type_t *ret_type = scc_ir_module_get_type(
|
|
||||||
GET_MODULE(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, &loc, SCC_AMD64_RAX);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
///< 函数返回
|
|
||||||
case SCC_IR_VALUE_TAG_RET: {
|
|
||||||
if (value->data.ret.ret_val) {
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
parse_location(ctx, &loc, value->data.ret.ret_val);
|
|
||||||
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
|
|
||||||
}
|
|
||||||
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
|
|
||||||
scc_mcode_amd64_pop_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
|
|
||||||
scc_mcode_amd64_ret(&ctx->sect_mcode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
LOG_FATAL("unknown value type: %d", value->tag);
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock,
|
|
||||||
patch_vec_t *patches) {
|
|
||||||
|
|
||||||
// 打印基本块中的每条指令
|
|
||||||
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
|
|
||||||
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i);
|
|
||||||
parse_value(ctx, node_ref, patches);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 hash_func(const void *key) { return (u32)(usize)key; }
|
|
||||||
static int equal_func(const void *key1, const void *key2) {
|
|
||||||
return (usize)key1 - (usize)key2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scc_frame_alloc_ops_t *scc_frame_alloc_win64_ops(void);
|
|
||||||
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
|
||||||
// FIXME using other
|
|
||||||
ctx->noderef2regloc =
|
|
||||||
scc_reg_alloc_run(&ctx->reg_alloc, func, scc_frame_alloc_win64_ops());
|
|
||||||
ctx->stack_size = scc_reg_stack_size(&ctx->reg_alloc);
|
|
||||||
Assert(ctx->noderef2regloc);
|
|
||||||
|
|
||||||
usize bblock_cnt = scc_vec_size(func->bblocks);
|
|
||||||
usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize));
|
|
||||||
// 建立 bblock_ref -> id 的映射
|
|
||||||
scc_hashtable_t ref2id;
|
|
||||||
scc_hashtable_init(&ref2id, hash_func, equal_func);
|
|
||||||
for (usize i = 0; i < bblock_cnt; i++) {
|
|
||||||
scc_ir_bblock_ref_t ref = scc_vec_at(func->bblocks, i);
|
|
||||||
scc_hashtable_set(&ref2id, (void *)(usize)ref, (void *)i);
|
|
||||||
}
|
|
||||||
|
|
||||||
patch_vec_t patches;
|
|
||||||
scc_vec_init(patches);
|
|
||||||
|
|
||||||
scc_mcode_amd64_push_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
|
|
||||||
scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
|
|
||||||
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RBP,
|
|
||||||
SCC_AMD64_RSP, ctx->stack_size);
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
scc_vec_foreach(func->params, i) {
|
|
||||||
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
|
||||||
parse_location(ctx, &loc, node_ref);
|
|
||||||
if (i < 4) {
|
|
||||||
// 前 4 个参数:从寄存器存入槽位
|
|
||||||
int reg[] = {SCC_AMD64_RCX, SCC_AMD64_RDX, SCC_AMD64_R8,
|
|
||||||
SCC_AMD64_R9};
|
|
||||||
store_value_from_reg(ctx, &loc, reg[i]);
|
|
||||||
} else {
|
|
||||||
// 额外参数:从栈中加载到槽位
|
|
||||||
// 偏移 = 16 (old rbp+retaddr) + 32 (shadow) + (i-4)*8
|
|
||||||
int offset = 16 + 32 + (i - 4) * 8;
|
|
||||||
// 临时将栈值加载到 RAX,再存储到槽位
|
|
||||||
scc_mcode_amd64_mov_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
|
|
||||||
SCC_AMD64_RBP, offset);
|
|
||||||
store_value_from_reg(ctx, &loc, SCC_AMD64_RAX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
|
|
||||||
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
|
||||||
scc_ir_bblock_t *bblock =
|
|
||||||
scc_ir_module_get_bblock(GET_MODULE(ctx), bblock_ref);
|
|
||||||
|
|
||||||
if (bblock == nullptr) {
|
|
||||||
LOG_FATAL("<invalid block>\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bblock_offsets[i] = scc_vec_size(ctx->sect_mcode.mcode);
|
|
||||||
parse_bblock(ctx, bblock, &patches);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 回填所有跳转偏移
|
|
||||||
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode);
|
|
||||||
scc_vec_foreach(patches, idx) {
|
|
||||||
patch_t *p = &scc_vec_at(patches, idx);
|
|
||||||
usize target_id =
|
|
||||||
(usize)scc_hashtable_get(&ref2id, (void *)(usize)p->target_bb_ref);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
scc_free(bblock_offsets);
|
|
||||||
scc_vec_free(patches);
|
|
||||||
scc_hashtable_drop(&ref2id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
|
||||||
scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_strategy_pure_stack,
|
|
||||||
GET_MODULE(ctx));
|
|
||||||
|
|
||||||
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 != nullptr);
|
|
||||||
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.fields, j) {
|
|
||||||
scc_vec_push(ctx->sect_data,
|
|
||||||
scc_vec_at(value->data.const_array.fields, 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_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");
|
|
||||||
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_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");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sccf_sym_t *sym =
|
|
||||||
sccf_builder_get_symbol_unsafe(ctx->builder, func->name);
|
|
||||||
Assert(sym != nullptr);
|
|
||||||
sym->sccf_sect_offset = scc_vec_size(ctx->sect_mcode.mcode);
|
|
||||||
parse_function(ctx, func);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *buf = scc_vec_unsafe_get_data(ctx->sect_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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sccf_sect_data_t text_section;
|
|
||||||
scc_vec_unsafe_from_buffer(text_section,
|
|
||||||
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_builder_add_data_section(ctx->builder, &ctx->sect_data);
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#include <reg_alloc.h>
|
|
||||||
#include <type_manager.h>
|
|
||||||
|
|
||||||
static u32 hash_func(const void *key) { return (usize)key; }
|
|
||||||
static int equal_func(const void *key1, const void *key2) {
|
|
||||||
return (usize)key1 - (usize)key2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t strategy,
|
|
||||||
scc_ir_module_t *ir_module) {
|
|
||||||
ctx->frame_alloc = nullptr;
|
|
||||||
ctx->ir_module = ir_module;
|
|
||||||
scc_hashtable_init(&ctx->node2loc, hash_func, equal_func);
|
|
||||||
scc_vec_init(ctx->loc_vec);
|
|
||||||
ctx->reg_alloc_func = strategy;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define add_loc(ctx, loc, val_ref) \
|
|
||||||
do { \
|
|
||||||
scc_vec_push(ctx->loc_vec, loc); \
|
|
||||||
scc_hashtable_set(&ctx->node2loc, (void *)(usize)val_ref, \
|
|
||||||
(void *)(usize)(scc_vec_size(ctx->loc_vec))); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
void scc_reg_alloc_strategy_pure_stack(scc_reg_alloc_t *ctx,
|
|
||||||
scc_ir_func_t *func,
|
|
||||||
scc_frame_alloc_ops_t *frame_alloc) {
|
|
||||||
scc_reg_loc_t loc;
|
|
||||||
|
|
||||||
// 为参数分配槽位(参数通过寄存器传入,但需要保存到栈上)
|
|
||||||
scc_vec_foreach(func->params, i) {
|
|
||||||
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
|
||||||
loc.kind = SCC_REG_KIND_STACK_ADDR;
|
|
||||||
loc.data.slot_idx =
|
|
||||||
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0); // 参数按8字节
|
|
||||||
add_loc(ctx, loc, node_ref);
|
|
||||||
}
|
|
||||||
// 遍历所有指令,为需要存储结果的节点分配槽位
|
|
||||||
scc_vec_foreach(func->bblocks, i) {
|
|
||||||
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
|
||||||
scc_ir_bblock_t *bblock =
|
|
||||||
scc_ir_module_get_bblock(ctx->ir_module, bblock_ref);
|
|
||||||
scc_vec_foreach(bblock->instrs, j) {
|
|
||||||
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);
|
|
||||||
if (node == nullptr)
|
|
||||||
continue;
|
|
||||||
switch (node->tag) {
|
|
||||||
case SCC_IR_VALUE_TAG_LOAD:
|
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
|
||||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
|
||||||
case SCC_IR_VALUE_TAG_CALL: // 返回值
|
|
||||||
loc.kind = SCC_REG_KIND_STACK;
|
|
||||||
loc.data.slot_idx =
|
|
||||||
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0);
|
|
||||||
add_loc(ctx, loc, node_ref);
|
|
||||||
break;
|
|
||||||
case SCC_IR_VALUE_TAG_ALLOC: {
|
|
||||||
scc_ir_type_t *type =
|
|
||||||
scc_ir_module_get_type(ctx->ir_module, node->type);
|
|
||||||
Assert(type->tag == SCC_IR_TYPE_PTR);
|
|
||||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
|
||||||
ctx->ir_module, type->data.pointer.base);
|
|
||||||
int size = scc_ir2mcode_type_width(ctx->ir_module, base_type);
|
|
||||||
|
|
||||||
loc.kind = SCC_REG_KIND_STACK_ADDR;
|
|
||||||
loc.data.slot_idx = frame_alloc->alloc_local_slot(
|
|
||||||
frame_alloc, size, 0, node->name);
|
|
||||||
add_loc(ctx, loc, node_ref);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#include <scc_ir2mcode.h>
|
|
||||||
|
|
||||||
void scc_ir2mcode_init(scc_ir2mcode_ctx_t *ctx, scc_ir_cprog_t *cprog,
|
|
||||||
sccf_builder_t *builder, scc_mcode_arch_t arch) {
|
|
||||||
ctx->cprog = cprog;
|
|
||||||
ctx->builder = builder;
|
|
||||||
scc_mcode_init(&ctx->sect_mcode, arch);
|
|
||||||
scc_vec_init(ctx->sect_data);
|
|
||||||
sccf_builder_init(ctx->builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scc_ir2mcode_drop(scc_ir2mcode_ctx_t *ctx) {
|
|
||||||
// TODO drop all objs
|
|
||||||
scc_ir_cprog_drop(ctx->cprog);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx);
|
|
||||||
|
|
||||||
void scc_ir2mcode(scc_ir2mcode_ctx_t *ctx) { scc_ir2amd64(ctx); }
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#include <type_manager.h>
|
|
||||||
|
|
||||||
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type) {
|
|
||||||
/* clang-format off */
|
|
||||||
if (ctx == nullptr || type == nullptr) {
|
|
||||||
Panic("Invalid argument");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
case SCC_IR_TYPE_ARRAY:
|
|
||||||
return scc_ir2mcode_type_width(
|
|
||||||
ctx,
|
|
||||||
scc_ir_module_get_type(ctx, type->data.array.base)
|
|
||||||
) * type->data.array.len;
|
|
||||||
default: return 8; // 默认64位
|
|
||||||
}
|
|
||||||
/* clang-format on */
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
#include <scc_ast2ir.h>
|
|
||||||
#include <scc_ir2mcode.h>
|
|
||||||
#include <scc_lexer.h>
|
|
||||||
#include <scc_parser.h>
|
|
||||||
#include <sccf2pe.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
void test_example(const char *input, cbool need_sema, const char *name) {
|
|
||||||
int res = 0;
|
|
||||||
scc_sstream_t mem_stream;
|
|
||||||
res = scc_sstream_init_by_buffer(&mem_stream, input, scc_strlen(input),
|
|
||||||
false, 16);
|
|
||||||
Assert(res == 0);
|
|
||||||
|
|
||||||
scc_lexer_t lexer;
|
|
||||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&mem_stream));
|
|
||||||
|
|
||||||
scc_lexer_tok_ring_t *tok_ring = scc_lexer_to_ring(&lexer, 64, false);
|
|
||||||
|
|
||||||
scc_parser_t parser;
|
|
||||||
if (need_sema) {
|
|
||||||
scc_sema_callbacks_t sema_callbacks;
|
|
||||||
scc_sema_init(&sema_callbacks);
|
|
||||||
scc_parser_init(&parser, tok_ring, &sema_callbacks);
|
|
||||||
} else {
|
|
||||||
scc_parser_init(&parser, tok_ring, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
scc_ast_translation_unit_t *tu = scc_parse_translation_unit(&parser);
|
|
||||||
|
|
||||||
scc_ast2ir_ctx_t ast2ir_ctx;
|
|
||||||
#include <abi/win_x64_type_abi.h>
|
|
||||||
scc_ir_cprog_t cprog;
|
|
||||||
scc_ir_cprog_init(&cprog);
|
|
||||||
scc_ast2ir_ctx_init(&ast2ir_ctx, scc_win_x64_type_abi, &cprog);
|
|
||||||
scc_ast2ir_translation_unit(&ast2ir_ctx, tu);
|
|
||||||
scc_ast2ir_ctx_drop(&ast2ir_ctx);
|
|
||||||
|
|
||||||
scc_ir2mcode_ctx_t ir2mcode_ctx;
|
|
||||||
sccf_builder_t sccf_builder;
|
|
||||||
scc_ir2mcode_init(&ir2mcode_ctx, &cprog, &sccf_builder,
|
|
||||||
SCC_MCODE_ARCH_AMD64);
|
|
||||||
scc_ir2mcode(&ir2mcode_ctx);
|
|
||||||
scc_ir2mcode_drop(&ir2mcode_ctx);
|
|
||||||
|
|
||||||
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
|
|
||||||
scc_pe_builder_t pe_builder;
|
|
||||||
sccf2pe(&pe_builder, sccf);
|
|
||||||
|
|
||||||
char fname[1024] = {0};
|
|
||||||
scc_snprintf(fname, sizeof(fname), "%s%s%s", __FILE__, "/../../", name);
|
|
||||||
scc_pe_dump_to_file(&pe_builder, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
test_example("int main() {\n"
|
|
||||||
" int a;\n"
|
|
||||||
" int b;\n"
|
|
||||||
" a = 1 + 2 * 3;\n"
|
|
||||||
" b = 7;\n"
|
|
||||||
" a = a - b + 1;\n"
|
|
||||||
" return a;\n"
|
|
||||||
"}\n",
|
|
||||||
true, "02_decl_expr.exe");
|
|
||||||
test_example("int main(void) {\n"
|
|
||||||
" int a;\n"
|
|
||||||
" a = 1;\n"
|
|
||||||
" if (a) {\n"
|
|
||||||
" a = 1;\n"
|
|
||||||
" } else {\n"
|
|
||||||
" a = 2;\n"
|
|
||||||
" }\n"
|
|
||||||
" return a;\n"
|
|
||||||
"}\n",
|
|
||||||
true, "04_if.exe");
|
|
||||||
test_example("int main() {\n"
|
|
||||||
" int i = 0;\n"
|
|
||||||
" while (i < 10) i = i + 1;\n"
|
|
||||||
" return i;\n"
|
|
||||||
"}\n",
|
|
||||||
true, "07_while.exe");
|
|
||||||
test_example("int add(int a, int b) {\n"
|
|
||||||
" return a + b;\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"int main(void) {\n"
|
|
||||||
" return add(1, 2);\n"
|
|
||||||
"}\n",
|
|
||||||
true, "10_main.exe");
|
|
||||||
test_example("int factorial(int);\n"
|
|
||||||
"\n"
|
|
||||||
"int main() {\n"
|
|
||||||
" int num = 5;\n"
|
|
||||||
" int result = factorial(num);\n"
|
|
||||||
" // printf(\"%d\", result);\n"
|
|
||||||
" return result;\n"
|
|
||||||
"}\n"
|
|
||||||
"\n"
|
|
||||||
"int factorial(int num) {\n"
|
|
||||||
" if (num == 0) {\n"
|
|
||||||
" return 1;\n"
|
|
||||||
" } else {\n"
|
|
||||||
" return num * factorial(num - 1);\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n",
|
|
||||||
true, "11_recursion.exe");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -947,9 +947,12 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Check validation
|
// TODO Check validation
|
||||||
param = SCC_AST_CAST_TO(scc_ast_decl_t, decl);
|
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||||
Assert(param->base.type = SCC_AST_DECL_VAR);
|
Assert(param != nullptr);
|
||||||
param->base.type = SCC_AST_DECL_PARAM;
|
scc_ast_decl_param_init(param, decl->var.type, decl->name,
|
||||||
|
scc_vec_size(*params), decl->base.loc);
|
||||||
|
// FIXME free all node
|
||||||
|
scc_free(decl);
|
||||||
|
|
||||||
scc_vec_push(*params, param);
|
scc_vec_push(*params, param);
|
||||||
|
|
||||||
@@ -968,7 +971,8 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
|||||||
Assert(type != nullptr);
|
Assert(type != nullptr);
|
||||||
scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST,
|
scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||||
tok_ptr->loc);
|
tok_ptr->loc);
|
||||||
scc_ast_decl_param_init(param, type, nullptr, tok_ptr->loc);
|
scc_ast_decl_param_init(param, type, nullptr, scc_vec_size(*params),
|
||||||
|
tok_ptr->loc);
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
scc_vec_push(*params, param);
|
scc_vec_push(*params, param);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -3,9 +3,7 @@
|
|||||||
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||||
symtab->root_scope.parent = nullptr;
|
symtab->root_scope.parent = nullptr;
|
||||||
|
|
||||||
scc_hashtable_init(&symtab->root_scope.symbols,
|
scc_hashtable_cstr_init(&symtab->root_scope.symbols);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
symtab->current_scope = &symtab->root_scope;
|
symtab->current_scope = &symtab->root_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,9 +21,7 @@ void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scope->parent = symtab->current_scope;
|
scope->parent = symtab->current_scope;
|
||||||
scc_hashtable_init(&scope->symbols,
|
scc_hashtable_cstr_init(&scope->symbols);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
symtab->current_scope = scope;
|
symtab->current_scope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ static void test_function_type(void) {
|
|||||||
{
|
{
|
||||||
// int (void)
|
// int (void)
|
||||||
scc_ast_decl_t void_param;
|
scc_ast_decl_t void_param;
|
||||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_param, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
@@ -189,9 +189,9 @@ static void test_function_type(void) {
|
|||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_t param_int, param_float;
|
scc_ast_decl_t param_int, param_float;
|
||||||
scc_ast_decl_param_init(¶m_int, &int_type, nullptr,
|
scc_ast_decl_param_init(¶m_int, &int_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_param_init(¶m_float, &float_type, nullptr,
|
scc_ast_decl_param_init(¶m_float, &float_type, nullptr, 1,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
@@ -213,9 +213,9 @@ static void test_function_type(void) {
|
|||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_t param_int, param_var;
|
scc_ast_decl_t param_int, param_var;
|
||||||
scc_ast_decl_param_init(¶m_int, &int_type, nullptr,
|
scc_ast_decl_param_init(¶m_int, &int_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_param_init(¶m_var, &va_list_type, "...",
|
scc_ast_decl_param_init(¶m_var, &va_list_type, "...", 1,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
@@ -242,7 +242,7 @@ static void test_function_type(void) {
|
|||||||
{
|
{
|
||||||
// int (*)(void)
|
// int (*)(void)
|
||||||
scc_ast_decl_t void_param;
|
scc_ast_decl_t void_param;
|
||||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_param, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
@@ -495,7 +495,7 @@ static void test_hard_type(void) {
|
|||||||
{
|
{
|
||||||
// 1) 函数类型 int (void)
|
// 1) 函数类型 int (void)
|
||||||
scc_ast_decl_t void_param;
|
scc_ast_decl_t void_param;
|
||||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_param, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
scc_vec_init(params);
|
scc_vec_init(params);
|
||||||
@@ -543,7 +543,7 @@ static void test_hard_type(void) {
|
|||||||
|
|
||||||
// 3) 函数类型,返回上述指针,无参数
|
// 3) 函数类型,返回上述指针,无参数
|
||||||
scc_ast_decl_t void_param;
|
scc_ast_decl_t void_param;
|
||||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_param, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
scc_vec_init(params);
|
scc_vec_init(params);
|
||||||
@@ -566,7 +566,7 @@ static void test_hard_type(void) {
|
|||||||
{
|
{
|
||||||
// 1) 函数类型 int (void)
|
// 1) 函数类型 int (void)
|
||||||
scc_ast_decl_t void_param;
|
scc_ast_decl_t void_param;
|
||||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_param, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
scc_vec_init(params);
|
scc_vec_init(params);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ static void test_parser_unit(void) {
|
|||||||
scc_ast_type_t func_type;
|
scc_ast_type_t func_type;
|
||||||
scc_ast_decl_vec_t func_params;
|
scc_ast_decl_vec_t func_params;
|
||||||
scc_ast_decl_t void_decl;
|
scc_ast_decl_t void_decl;
|
||||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_decl, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *array[] = {&void_decl};
|
scc_ast_decl_t *array[] = {&void_decl};
|
||||||
scc_vec_unsafe_from_static_array(func_params, array);
|
scc_vec_unsafe_from_static_array(func_params, array);
|
||||||
@@ -67,7 +67,7 @@ static void test_parser_unit(void) {
|
|||||||
scc_ast_type_t func_type;
|
scc_ast_type_t func_type;
|
||||||
scc_ast_decl_vec_t func_params;
|
scc_ast_decl_vec_t func_params;
|
||||||
scc_ast_decl_t void_decl;
|
scc_ast_decl_t void_decl;
|
||||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_decl, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *array[] = {&void_decl};
|
scc_ast_decl_t *array[] = {&void_decl};
|
||||||
scc_vec_unsafe_from_static_array(func_params, array);
|
scc_vec_unsafe_from_static_array(func_params, array);
|
||||||
@@ -116,7 +116,7 @@ static void test_parser_unit(void) {
|
|||||||
scc_ast_type_t func_type;
|
scc_ast_type_t func_type;
|
||||||
scc_ast_decl_vec_t func_params;
|
scc_ast_decl_vec_t func_params;
|
||||||
scc_ast_decl_t void_decl;
|
scc_ast_decl_t void_decl;
|
||||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_decl, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *array[] = {&void_decl};
|
scc_ast_decl_t *array[] = {&void_decl};
|
||||||
scc_vec_unsafe_from_static_array(func_params, array);
|
scc_vec_unsafe_from_static_array(func_params, array);
|
||||||
@@ -319,14 +319,14 @@ static void test_parser_unit(void) {
|
|||||||
{
|
{
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
scc_ast_decl_t param0;
|
scc_ast_decl_t param0;
|
||||||
scc_ast_decl_param_init(¶m0, (scc_ast_type_t *)&int_type, "a",
|
scc_ast_decl_param_init(¶m0, (scc_ast_type_t *)&int_type, "a", 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t param1;
|
scc_ast_decl_t param1;
|
||||||
scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b",
|
scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b", 1,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t param2;
|
scc_ast_decl_t param2;
|
||||||
scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type,
|
scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type,
|
||||||
nullptr, scc_pos_create());
|
nullptr, 2, scc_pos_create());
|
||||||
scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2};
|
scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2};
|
||||||
scc_vec_unsafe_from_static_array(params, params_array);
|
scc_vec_unsafe_from_static_array(params, params_array);
|
||||||
scc_ast_type_t decl_func_type;
|
scc_ast_type_t decl_func_type;
|
||||||
@@ -433,11 +433,11 @@ static void test_parser_unit(void) {
|
|||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
scc_ast_decl_t param1;
|
scc_ast_decl_t param1;
|
||||||
scc_ast_decl_param_init(¶m1, &type_type, "a", scc_pos_create());
|
scc_ast_decl_param_init(¶m1, &type_type, "a", 0, scc_pos_create());
|
||||||
scc_ast_decl_t param2;
|
scc_ast_decl_t param2;
|
||||||
scc_ast_decl_param_init(¶m2, &int_type, "b", scc_pos_create());
|
scc_ast_decl_param_init(¶m2, &int_type, "b", 1, scc_pos_create());
|
||||||
scc_ast_decl_t param3;
|
scc_ast_decl_t param3;
|
||||||
scc_ast_decl_param_init(¶m3, &va_list_type, nullptr,
|
scc_ast_decl_param_init(¶m3, &va_list_type, nullptr, 2,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3};
|
scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3};
|
||||||
scc_ast_decl_vec_t func_params;
|
scc_ast_decl_vec_t func_params;
|
||||||
@@ -495,7 +495,7 @@ static void test_parser_unit(void) {
|
|||||||
|
|
||||||
// 2. 参数声明
|
// 2. 参数声明
|
||||||
scc_ast_decl_t param_decl;
|
scc_ast_decl_t param_decl;
|
||||||
scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt",
|
scc_ast_decl_param_init(¶m_decl, &ptr_to_char, "fmt", 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
|
|
||||||
// 3. 返回类型:void *
|
// 3. 返回类型:void *
|
||||||
@@ -814,7 +814,7 @@ static void test_parser_unit(void) {
|
|||||||
scc_ast_type_t func_type;
|
scc_ast_type_t func_type;
|
||||||
scc_ast_decl_vec_t func_params;
|
scc_ast_decl_vec_t func_params;
|
||||||
scc_ast_decl_t void_decl;
|
scc_ast_decl_t void_decl;
|
||||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
scc_ast_decl_param_init(&void_decl, &void_type, nullptr, 0,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *array[] = {&void_decl};
|
scc_ast_decl_t *array[] = {&void_decl};
|
||||||
scc_vec_unsafe_from_static_array(func_params, array);
|
scc_vec_unsafe_from_static_array(func_params, array);
|
||||||
@@ -841,12 +841,13 @@ static void test_parser_unit(void) {
|
|||||||
scc_ast_type_t func_hard_type;
|
scc_ast_type_t func_hard_type;
|
||||||
|
|
||||||
scc_ast_decl_t param1;
|
scc_ast_decl_t param1;
|
||||||
scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar", scc_pos_create());
|
scc_ast_decl_param_init(¶m1, &ptr_to_func, "bar", 0,
|
||||||
|
scc_pos_create());
|
||||||
scc_ast_decl_t param2;
|
scc_ast_decl_t param2;
|
||||||
scc_ast_decl_param_init(¶m2, &typedef_func_type, "a",
|
scc_ast_decl_param_init(¶m2, &typedef_func_type, "a", 1,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t param3;
|
scc_ast_decl_t param3;
|
||||||
scc_ast_decl_param_init(¶m1, &va_list_type, nullptr,
|
scc_ast_decl_param_init(¶m1, &va_list_type, nullptr, 2,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3};
|
scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3};
|
||||||
scc_ast_decl_vec_t func_hard_params;
|
scc_ast_decl_vec_t func_hard_params;
|
||||||
|
|||||||
@@ -126,12 +126,14 @@ cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 hash_func(const void *key) {
|
static u32 hash_func(const void *key, void *userdata) {
|
||||||
|
(void)userdata;
|
||||||
const scc_str_t *string = (const scc_str_t *)key;
|
const scc_str_t *string = (const scc_str_t *)key;
|
||||||
return scc_strhash32(scc_str_as_cstr(string));
|
return scc_strhash32(scc_str_as_cstr(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hash_cmp(const void *key1, const void *key2) {
|
static int hash_cmp(const void *key1, const void *key2, void *userdata) {
|
||||||
|
(void)userdata;
|
||||||
const scc_str_t *str1 = (const scc_str_t *)key1;
|
const scc_str_t *str1 = (const scc_str_t *)key1;
|
||||||
const scc_str_t *str2 = (const scc_str_t *)key2;
|
const scc_str_t *str2 = (const scc_str_t *)key2;
|
||||||
|
|
||||||
@@ -143,7 +145,7 @@ static int hash_cmp(const void *key1, const void *key2) {
|
|||||||
|
|
||||||
void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros) {
|
void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros) {
|
||||||
Assert(macros != nullptr);
|
Assert(macros != nullptr);
|
||||||
scc_hashtable_init(¯os->table, hash_func, hash_cmp);
|
scc_hashtable_init(¯os->table, hash_func, hash_cmp, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int macro_free(const void *key, void *value, void *context) {
|
static int macro_free(const void *key, void *value, void *context) {
|
||||||
|
|||||||
@@ -3,12 +3,8 @@
|
|||||||
void sccf_builder_init(sccf_builder_t *builder) {
|
void sccf_builder_init(sccf_builder_t *builder) {
|
||||||
builder->aligned = 64;
|
builder->aligned = 64;
|
||||||
sccf_init(&builder->sccf);
|
sccf_init(&builder->sccf);
|
||||||
scc_hashtable_init(&builder->str2offset,
|
scc_hashtable_cstr_init(&builder->str2offset);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
scc_hashtable_cstr_init(&builder->str2sym);
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
scc_hashtable_init(&builder->str2sym,
|
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
|
|
||||||
scc_vec_init(builder->strtab);
|
scc_vec_init(builder->strtab);
|
||||||
scc_vec_init(builder->relocs);
|
scc_vec_init(builder->relocs);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#ifndef __SCC_SSTREAM_H__
|
#ifndef __SCC_SSTREAM_H__
|
||||||
#define __SCC_SSTREAM_H__
|
#define __SCC_SSTREAM_H__
|
||||||
|
|
||||||
#include "scc_pos.h"
|
|
||||||
#include "scc_pos_log.h"
|
|
||||||
#include <scc_core.h>
|
#include <scc_core.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
|
#include <scc_pos.h>
|
||||||
|
#include <scc_pos_log.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_pos_t pos;
|
scc_pos_t pos;
|
||||||
|
|||||||
@@ -18,9 +18,7 @@ static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder,
|
|||||||
static void scc_winpe_hnt_builder_init(scc_pe_hnt_builder_t *builder) {
|
static void scc_winpe_hnt_builder_init(scc_pe_hnt_builder_t *builder) {
|
||||||
scc_vec_init(builder->data);
|
scc_vec_init(builder->data);
|
||||||
builder->section_offset = 0;
|
builder->section_offset = 0;
|
||||||
scc_hashtable_init(&builder->str_map,
|
scc_hashtable_cstr_init(&builder->str_map);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder,
|
static void scc_winpe_hnt_builder_push(scc_pe_hnt_builder_t *builder,
|
||||||
@@ -61,9 +59,7 @@ void scc_pe_idata_builder_init(scc_pe_idata_builder_t *builder,
|
|||||||
|
|
||||||
scc_winpe_hnt_builder_init(&builder->hnt_builder);
|
scc_winpe_hnt_builder_init(&builder->hnt_builder);
|
||||||
|
|
||||||
scc_hashtable_init(&builder->iat_map,
|
scc_hashtable_cstr_init(&builder->iat_map);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) {
|
u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) {
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
|
|||||||
|
|
||||||
// scc_pe_name_vec_t symbol_names;
|
// scc_pe_name_vec_t symbol_names;
|
||||||
usize line = 0;
|
usize line = 0;
|
||||||
|
// FIXME
|
||||||
|
buffer[fsize - 1] = '\0';
|
||||||
for (usize i = 0; i < fsize; i += 1) {
|
for (usize i = 0; i < fsize; i += 1) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
line += 1;
|
line += 1;
|
||||||
@@ -61,9 +63,7 @@ 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, const char *find_path) {
|
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
|
||||||
// Got .dll.def
|
// Got .dll.def
|
||||||
|
|
||||||
scc_hashtable_init(&ctx->str2libsym,
|
scc_hashtable_cstr_init(&ctx->str2libsym);
|
||||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
scc_vec_init(ctx->idata_libs);
|
scc_vec_init(ctx->idata_libs);
|
||||||
ctx->find_path = find_path;
|
ctx->find_path = find_path;
|
||||||
load_from_def(ctx, ctx->find_path, "msvcrt.dll");
|
load_from_def(ctx, ctx->find_path, "msvcrt.dll");
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
|||||||
va_list args_copy;
|
va_list args_copy;
|
||||||
va_copy(args_copy, args);
|
va_copy(args_copy, args);
|
||||||
|
|
||||||
// 先计算所需长度
|
|
||||||
int required_size = vsnprintf_(nullptr, 0, format, args_copy);
|
int required_size = vsnprintf_(nullptr, 0, format, args_copy);
|
||||||
va_end(args_copy);
|
va_end(args_copy);
|
||||||
|
|
||||||
@@ -90,22 +89,20 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
char *buf = nullptr;
|
char *buf = nullptr;
|
||||||
|
char stack_buf[4096]; // 移到外部,作用域为整个函数
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
if (required_size < 4096) {
|
if (required_size < 4096) {
|
||||||
// 小输出使用栈上缓冲区
|
|
||||||
char stack_buf[4096];
|
|
||||||
size = vsnprintf_(stack_buf, sizeof(stack_buf), format, args);
|
size = vsnprintf_(stack_buf, sizeof(stack_buf), format, args);
|
||||||
buf = stack_buf;
|
buf = stack_buf;
|
||||||
} else {
|
} else {
|
||||||
// 大输出使用堆分配
|
|
||||||
buf = scc_pal_malloc(required_size + 1);
|
buf = scc_pal_malloc(required_size + 1);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
return -1;
|
return -1;
|
||||||
size = vsnprintf_(buf, required_size + 1, format, args);
|
size = vsnprintf_(buf, required_size + 1, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输出处理...
|
// 输出处理(现在 buf 始终有效)
|
||||||
if (file == scc_stdout) {
|
if (file == scc_stdout) {
|
||||||
scc_pal_write(buf, size);
|
scc_pal_write(buf, size);
|
||||||
} else if (file == scc_stderr) {
|
} else if (file == scc_stderr) {
|
||||||
@@ -114,14 +111,12 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) {
|
|||||||
scc_pal_fwrite(file, buf, size);
|
scc_pal_fwrite(file, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果使用了堆分配,释放内存
|
if (required_size >= 4096 && buf) {
|
||||||
if (buf && required_size >= 4096) {
|
|
||||||
scc_pal_free(buf);
|
scc_pal_free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scc_snprintf(char *buff, usize buff_size, const char *fmt, ...) {
|
int scc_snprintf(char *buff, usize buff_size, const char *fmt, ...) {
|
||||||
int ret;
|
int ret;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|||||||
@@ -33,8 +33,9 @@ typedef struct scc_hashtable_entry {
|
|||||||
scc_hashtable_entry_state_t state; /**< 当前条目状态 */
|
scc_hashtable_entry_state_t state; /**< 当前条目状态 */
|
||||||
} scc_hashtable_entry_t;
|
} scc_hashtable_entry_t;
|
||||||
|
|
||||||
typedef u32 (*scc_hashtable_hash_func_t)(const void *key);
|
typedef u32 (*scc_hashtable_hash_func_t)(const void *key, void *userdata);
|
||||||
typedef int (*scc_hashtable_equal_func_t)(const void *key1, const void *key2);
|
typedef int (*scc_hashtable_equal_func_t)(const void *key1, const void *key2,
|
||||||
|
void *userdata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @struct scc_hashtable_t
|
* @struct scc_hashtable_t
|
||||||
@@ -43,6 +44,7 @@ typedef int (*scc_hashtable_equal_func_t)(const void *key1, const void *key2);
|
|||||||
* 使用开放寻址法实现,采用墓碑标记处理删除操作
|
* 使用开放寻址法实现,采用墓碑标记处理删除操作
|
||||||
*/
|
*/
|
||||||
typedef struct scc_hashtable {
|
typedef struct scc_hashtable {
|
||||||
|
void *userdata;
|
||||||
SCC_VEC(scc_hashtable_entry_t) entries; /**< 条目存储容器 */
|
SCC_VEC(scc_hashtable_entry_t) entries; /**< 条目存储容器 */
|
||||||
u32 count; /**< 有效条目数量(不含墓碑) */
|
u32 count; /**< 有效条目数量(不含墓碑) */
|
||||||
u32 tombstone_count; /**< 墓碑条目数量 */
|
u32 tombstone_count; /**< 墓碑条目数量 */
|
||||||
@@ -69,7 +71,9 @@ typedef struct scc_hashtable {
|
|||||||
*/
|
*/
|
||||||
void scc_hashtable_init(scc_hashtable_t *ht,
|
void scc_hashtable_init(scc_hashtable_t *ht,
|
||||||
scc_hashtable_hash_func_t hash_func,
|
scc_hashtable_hash_func_t hash_func,
|
||||||
scc_hashtable_equal_func_t cmp_func);
|
scc_hashtable_equal_func_t cmp_func, void *userdata);
|
||||||
|
|
||||||
|
void scc_hashtable_cstr_init(scc_hashtable_t *ht);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 插入/更新键值对
|
* @brief 插入/更新键值对
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "scc_pos.h"
|
#include "scc_pos.h"
|
||||||
#include <scc_core.h>
|
#include <scc_core.h>
|
||||||
|
|
||||||
extern logger_t __scc_usr_log;
|
extern logger_t __scc_pos_log;
|
||||||
|
|
||||||
#define SCC_POS_LOG(level, pos, fmt, ...) \
|
#define SCC_POS_LOG(level, pos, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
@@ -13,7 +13,7 @@ extern logger_t __scc_usr_log;
|
|||||||
scc_pos_pnt_fmt ": ", scc_pos_pnt_val(pos)); \
|
scc_pos_pnt_fmt ": ", scc_pos_pnt_val(pos)); \
|
||||||
scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \
|
scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \
|
||||||
##__VA_ARGS__); \
|
##__VA_ARGS__); \
|
||||||
__scc_usr_log.handler(&__scc_usr_log, level, nullptr, 0, nullptr, \
|
__scc_pos_log.handler(&__scc_pos_log, level, nullptr, 0, nullptr, \
|
||||||
"%s", _full_msg); \
|
"%s", _full_msg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -6,16 +6,31 @@
|
|||||||
|
|
||||||
void scc_hashtable_init(scc_hashtable_t *ht,
|
void scc_hashtable_init(scc_hashtable_t *ht,
|
||||||
scc_hashtable_hash_func_t hash_func,
|
scc_hashtable_hash_func_t hash_func,
|
||||||
scc_hashtable_equal_func_t cmp_func) {
|
scc_hashtable_equal_func_t cmp_func, void *userdata) {
|
||||||
|
|
||||||
scc_vec_init(ht->entries);
|
scc_vec_init(ht->entries);
|
||||||
ht->count = 0;
|
ht->count = 0;
|
||||||
ht->tombstone_count = 0;
|
ht->tombstone_count = 0;
|
||||||
ht->cmp_func = cmp_func;
|
ht->cmp_func = cmp_func;
|
||||||
ht->hash_func = hash_func;
|
ht->hash_func = hash_func;
|
||||||
|
ht->userdata = userdata;
|
||||||
Assert(ht->cmp_func != nullptr && ht->hash_func != nullptr);
|
Assert(ht->cmp_func != nullptr && ht->hash_func != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 ht_strhash(const void *key, void *userdata) {
|
||||||
|
(void)userdata;
|
||||||
|
return scc_strhash32(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ht_strcmp(const void *key1, const void *key2, void *userdata) {
|
||||||
|
(void)userdata;
|
||||||
|
return scc_strcmp(key1, key2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void scc_hashtable_cstr_init(scc_hashtable_t *ht) {
|
||||||
|
scc_hashtable_init(ht, ht_strhash, ht_strcmp, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
static int next_power_of_two(int n) {
|
static int next_power_of_two(int n) {
|
||||||
n--;
|
n--;
|
||||||
n |= n >> 1;
|
n |= n >> 1;
|
||||||
@@ -45,7 +60,8 @@ static scc_hashtable_entry_t *find_entry(scc_hashtable_t *ht, const void *key,
|
|||||||
if (entry->state == ENTRY_TOMBSTONE) {
|
if (entry->state == ENTRY_TOMBSTONE) {
|
||||||
if (!tombstone)
|
if (!tombstone)
|
||||||
tombstone = entry;
|
tombstone = entry;
|
||||||
} else if (entry->hash == hash && ht->cmp_func(entry->key, key) == 0) {
|
} else if (entry->hash == hash &&
|
||||||
|
ht->cmp_func(entry->key, key, ht->userdata) == 0) {
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +112,7 @@ void *scc_hashtable_set(scc_hashtable_t *ht, const void *key, void *value) {
|
|||||||
adjust_capacity(ht, new_cap);
|
adjust_capacity(ht, new_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 hash = ht->hash_func(key);
|
u32 hash = ht->hash_func(key, ht->userdata);
|
||||||
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
||||||
|
|
||||||
void *old_value = nullptr;
|
void *old_value = nullptr;
|
||||||
@@ -119,7 +135,7 @@ void *scc_hashtable_get(scc_hashtable_t *ht, const void *key) {
|
|||||||
if (ht->entries.cap == 0)
|
if (ht->entries.cap == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
u32 hash = ht->hash_func(key);
|
u32 hash = ht->hash_func(key, ht->userdata);
|
||||||
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
||||||
return (entry && entry->state == ENTRY_ACTIVE) ? entry->value : nullptr;
|
return (entry && entry->state == ENTRY_ACTIVE) ? entry->value : nullptr;
|
||||||
}
|
}
|
||||||
@@ -128,7 +144,7 @@ void *scc_hashtable_del(scc_hashtable_t *ht, const void *key) {
|
|||||||
if (ht->entries.cap == 0)
|
if (ht->entries.cap == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
u32 hash = ht->hash_func(key);
|
u32 hash = ht->hash_func(key, ht->userdata);
|
||||||
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
||||||
|
|
||||||
if (entry == nullptr || entry->state != ENTRY_ACTIVE)
|
if (entry == nullptr || entry->state != ENTRY_ACTIVE)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <scc_pos_log.h>
|
#include <scc_pos_log.h>
|
||||||
|
|
||||||
static int user_log_handler(logger_t *module, log_level_t level,
|
static int pos_log_handler(logger_t *module, log_level_t level,
|
||||||
const char *file, int line, const char *func,
|
const char *file, int line, const char *func,
|
||||||
const char *fmt, ...) {
|
const char *fmt, ...) {
|
||||||
|
|
||||||
@@ -50,8 +50,8 @@ static int user_log_handler(logger_t *module, log_level_t level,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger_t __scc_usr_log = {
|
logger_t __scc_pos_log = {
|
||||||
.name = "user",
|
.name = "pos_log",
|
||||||
.handler = user_log_handler,
|
.handler = pos_log_handler,
|
||||||
.level = LOG_LEVEL_ALL,
|
.level = LOG_LEVEL_ALL,
|
||||||
};
|
};
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
#include <scc_strpool.h>
|
#include <scc_strpool.h>
|
||||||
|
|
||||||
void scc_strpool_init(scc_strpool_t *pool) {
|
void scc_strpool_init(scc_strpool_t *pool) {
|
||||||
scc_hashtable_init(&pool->ht, (scc_hashtable_hash_func_t)scc_strhash32,
|
scc_hashtable_cstr_init(&pool->ht);
|
||||||
(scc_hashtable_equal_func_t)scc_strcmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *scc_strpool_intern(scc_strpool_t *pool, const char *str) {
|
const char *scc_strpool_intern(scc_strpool_t *pool, const char *str) {
|
||||||
|
|||||||
80
src/init.c
80
src/init.c
@@ -1,10 +1,86 @@
|
|||||||
|
#include <scc_core.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include <Windows.h>
|
||||||
#include <windows.h>
|
#include <signal.h>
|
||||||
|
/// Ddghelp.h 必须在 Windows.h 后定义
|
||||||
|
#include <Dbghelp.h>
|
||||||
|
|
||||||
|
static LONG WINAPI CreateMiniDump(EXCEPTION_POINTERS *pExceptionPointers) {
|
||||||
|
HANDLE hFile = CreateFileA("crash.dmp", GENERIC_WRITE, 0, NULL,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (hFile == INVALID_HANDLE_VALUE) {
|
||||||
|
scc_fprintf(scc_stderr, "Failed to create crash.dmp\n");
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
MINIDUMP_EXCEPTION_INFORMATION mei = {0};
|
||||||
|
BOOL bDumpWithException = FALSE;
|
||||||
|
|
||||||
|
if (pExceptionPointers != NULL) {
|
||||||
|
// 有异常上下文(来自 UnhandledExceptionFilter)
|
||||||
|
mei.ThreadId = GetCurrentThreadId();
|
||||||
|
mei.ExceptionPointers = pExceptionPointers;
|
||||||
|
mei.ClientPointers = FALSE;
|
||||||
|
bDumpWithException = TRUE;
|
||||||
|
} else {
|
||||||
|
// 没有异常上下文(例如来自 abort 信号),捕获当前线程上下文
|
||||||
|
CONTEXT ctx = {0};
|
||||||
|
ctx.ContextFlags = CONTEXT_FULL;
|
||||||
|
RtlCaptureContext(&ctx); // 获取当前执行点寄存器状态
|
||||||
|
|
||||||
|
static EXCEPTION_POINTERS fakeEP = {0};
|
||||||
|
static EXCEPTION_RECORD fakeER = {0};
|
||||||
|
fakeER.ExceptionCode = 0xE0000001; // 自定义异常码
|
||||||
|
fakeER.ExceptionFlags = 0;
|
||||||
|
fakeER.ExceptionRecord = NULL;
|
||||||
|
fakeER.ExceptionAddress = (PVOID)ctx.Rip; // 当前指令指针
|
||||||
|
fakeER.NumberParameters = 0;
|
||||||
|
|
||||||
|
fakeEP.ExceptionRecord = &fakeER;
|
||||||
|
fakeEP.ContextRecord = &ctx;
|
||||||
|
|
||||||
|
mei.ThreadId = GetCurrentThreadId();
|
||||||
|
mei.ExceptionPointers = &fakeEP;
|
||||||
|
mei.ClientPointers = FALSE;
|
||||||
|
bDumpWithException = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MINIDUMP_TYPE dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory);
|
||||||
|
|
||||||
|
BOOL bOK = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||||
|
hFile, dumpType,
|
||||||
|
bDumpWithException ? &mei : NULL, NULL, NULL);
|
||||||
|
CloseHandle(hFile);
|
||||||
|
|
||||||
|
if (bOK)
|
||||||
|
scc_fprintf(scc_stderr, "Minidump written: crash.dmp\n");
|
||||||
|
else
|
||||||
|
scc_fprintf(scc_stderr, "MiniDumpWriteDump failed: %lu\n",
|
||||||
|
GetLastError());
|
||||||
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SignalHandler(int sig) {
|
||||||
|
if (sig == SIGABRT) {
|
||||||
|
#ifdef DEV_MODE
|
||||||
|
CreateMiniDump(NULL);
|
||||||
|
#else
|
||||||
|
scc_fprintf(scc_stderr, "Press Enter to continue...");
|
||||||
|
getchar();
|
||||||
|
#endif
|
||||||
|
_exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void init_platform(void) {
|
void init_platform(void) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
signal(SIGABRT, SignalHandler);
|
||||||
|
#ifdef DEV_MODE
|
||||||
|
SetUnhandledExceptionFilter(CreateMiniDump);
|
||||||
|
#endif
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
SetConsoleCP(CP_UTF8);
|
SetConsoleCP(CP_UTF8);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
scc_str_t pproc_predefined_macros[] = {
|
scc_str_t pproc_predefined_macros[] = {
|
||||||
scc_str_from_cstr("__SCC__"),
|
scc_str_from_cstr("__SCC__"),
|
||||||
scc_str_from_cstr("_WIN64"),
|
scc_str_from_cstr("_WIN64"),
|
||||||
|
scc_str_from_cstr("_WIN32"),
|
||||||
scc_str_from_cstr("__x86_64__"),
|
scc_str_from_cstr("__x86_64__"),
|
||||||
};
|
};
|
||||||
for (usize i = 0; i < SCC_ARRLEN(pproc_predefined_macros); i += 1) {
|
for (usize i = 0; i < SCC_ARRLEN(pproc_predefined_macros); i += 1) {
|
||||||
|
|||||||
Reference in New Issue
Block a user