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:
zzy
2026-04-15 14:52:11 +08:00
parent 8054f20375
commit 5a9f816ccf
38 changed files with 260 additions and 1497 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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), &param_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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,3 +0,0 @@
#include <scc_ir.h>
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type);

View File

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

View File

@@ -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 地址加载到 RDIrep 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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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(&param_int, &int_type, nullptr, scc_ast_decl_param_init(&param_int, &int_type, nullptr, 0,
scc_pos_create()); scc_pos_create());
scc_ast_decl_param_init(&param_float, &float_type, nullptr, scc_ast_decl_param_init(&param_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(&param_int, &int_type, nullptr, scc_ast_decl_param_init(&param_int, &int_type, nullptr, 0,
scc_pos_create()); scc_pos_create());
scc_ast_decl_param_init(&param_var, &va_list_type, "...", scc_ast_decl_param_init(&param_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);

View File

@@ -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(&param0, (scc_ast_type_t *)&int_type, "a", scc_ast_decl_param_init(&param0, (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(&param1, (scc_ast_type_t *)&int_type, "b", scc_ast_decl_param_init(&param1, (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(&param2, (scc_ast_type_t *)&va_list_type, scc_ast_decl_param_init(&param2, (scc_ast_type_t *)&va_list_type,
nullptr, scc_pos_create()); nullptr, 2, scc_pos_create());
scc_ast_decl_t *params_array[] = {&param0, &param1, &param2}; scc_ast_decl_t *params_array[] = {&param0, &param1, &param2};
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(&param1, &type_type, "a", scc_pos_create()); scc_ast_decl_param_init(&param1, &type_type, "a", 0, scc_pos_create());
scc_ast_decl_t param2; scc_ast_decl_t param2;
scc_ast_decl_param_init(&param2, &int_type, "b", scc_pos_create()); scc_ast_decl_param_init(&param2, &int_type, "b", 1, scc_pos_create());
scc_ast_decl_t param3; scc_ast_decl_t param3;
scc_ast_decl_param_init(&param3, &va_list_type, nullptr, scc_ast_decl_param_init(&param3, &va_list_type, nullptr, 2,
scc_pos_create()); scc_pos_create());
scc_ast_decl_t *params_array[] = {&param1, &param2, &param3}; scc_ast_decl_t *params_array[] = {&param1, &param2, &param3};
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(&param_decl, &ptr_to_char, "fmt", scc_ast_decl_param_init(&param_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(&param1, &ptr_to_func, "bar", scc_pos_create()); scc_ast_decl_param_init(&param1, &ptr_to_func, "bar", 0,
scc_pos_create());
scc_ast_decl_t param2; scc_ast_decl_t param2;
scc_ast_decl_param_init(&param2, &typedef_func_type, "a", scc_ast_decl_param_init(&param2, &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(&param1, &va_list_type, nullptr, scc_ast_decl_param_init(&param1, &va_list_type, nullptr, 2,
scc_pos_create()); scc_pos_create());
scc_ast_decl_t *func_hard_array[] = {&param1, &param2, &param3}; scc_ast_decl_t *func_hard_array[] = {&param1, &param2, &param3};
scc_ast_decl_vec_t func_hard_params; scc_ast_decl_vec_t func_hard_params;

View File

@@ -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(&macros->table, hash_func, hash_cmp); scc_hashtable_init(&macros->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) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 插入/更新键值对

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
#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, ...) {
/* clang-format off */ /* clang-format off */
(void) module, (void)file, (void)line, (void)func; // 不再使用 (void) module, (void)file, (void)line, (void)func; // 不再使用
@@ -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,
}; };

View File

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

View File

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

View File

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