diff --git a/libs/abi/src/scc_type_abi.c b/libs/abi/src/scc_type_abi.c index 46969d3..933665e 100644 --- a/libs/abi/src/scc_type_abi.c +++ b/libs/abi/src/scc_type_abi.c @@ -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) { case SCC_AST_BUILTIN_TYPE_VOID: kind = SCC_ABI_TYPE_VOID; + break; case SCC_AST_BUILTIN_TYPE_CHAR: kind = SCC_ABI_TYPE_CHAR; break; diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index 3222b12..c7d496d 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -429,6 +429,7 @@ struct scc_ast_decl { // 参数声明 struct { scc_ast_type_t *type; + int param_idx; } param; // 结构体/联合/枚举声明 struct { diff --git a/libs/ast/include/scc_ast.h b/libs/ast/include/scc_ast.h index bdfa606..ddba964 100644 --- a/libs/ast/include/scc_ast.h +++ b/libs/ast/include/scc_ast.h @@ -74,12 +74,14 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl, // name can be nullptr static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl, 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); decl->base.loc = loc; decl->base.type = SCC_AST_DECL_PARAM; decl->name = name; decl->param.type = type; + decl->param.param_idx = idx; } static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl, diff --git a/libs/ast2ir/include/scc_ast2ir.h b/libs/ast2ir/include/scc_ast2ir.h index 13de28f..7ca099d 100644 --- a/libs/ast2ir/include/scc_ast2ir.h +++ b/libs/ast2ir/include/scc_ast2ir.h @@ -12,6 +12,7 @@ typedef struct { scc_hashtable_t symtab; ///< symbol to ir_ref // scc_strpool_t strpool; ///< string pool const scc_abi_type_calc_t *abi; + cbool hint_using_value; // 转换时尽可能使用value而不是alloc } scc_ast2ir_ctx_t; void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index e0fe233..85a3e36 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -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); switch (layout.size) { + case 0: + return scc_ir_builder_type_void(&ctx->builder); case 1: return scc_ir_builder_type_i8(&ctx->builder); 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_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_bblock_ref_t end_block = + scc_ir_value_ref_t end_block = 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) { // a && b - scc_ir_bblock_ref_t false_block = + scc_ir_value_ref_t false_block = scc_ir_builder_bblock(&ctx->builder, "and_false"); // 如果左操作数为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 // a || b - scc_ir_bblock_ref_t true_block = + scc_ir_value_ref_t true_block = scc_ir_builder_bblock(&ctx->builder, "or_true"); // 如果左操作数非0,结果为1(短路) @@ -708,13 +710,13 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) { \ / 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_bblock_ref_t false_block = + scc_ir_value_ref_t false_block = 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_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; } 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_bblock_ref_t body_block = + scc_ir_value_ref_t body_block = 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_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; } 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_bblock_ref_t body_block = + scc_ir_value_ref_t body_block = 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_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; } 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_bblock_ref_t body_block = + scc_ir_value_ref_t body_block = 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"); 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_func_ref_t func_ref = (usize)scc_hashtable_get(&ctx->symtab, decl->name); - if (func_ref == 0) { + if (func_ref == SCC_IR_REF_nullptr) { func_ref = scc_ir_builder_func(&ctx->builder, func_type_ref, 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_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_vec_foreach(decl->func.type->function.params, i) { scc_ast_decl_t *param = scc_vec_at(decl->func.type->function.params, i); - - 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_decl(ctx, param, false); } + scc_ast2ir_stmt(ctx, decl->func.body); // FIXME need ret for none return or other default ret 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; } 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; } 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 int scc_cmp_node(const void *key1, const void *key2) { +static u32 scc_hash_node(const void *key, void *userdata) { + return (u32)(usize)key; +} +static int scc_cmp_node(const void *key1, const void *key2, void *userdata) { 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); ctx->abi = abi; scc_ir_builder_init(&ctx->builder, cprog); - scc_hashtable_init(&ctx->ast2ir_cache, scc_hash_node, scc_cmp_node); - scc_hashtable_init(&ctx->symtab, (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_init(&ctx->ast2ir_cache, scc_hash_node, scc_cmp_node, + nullptr); + scc_hashtable_cstr_init(&ctx->symtab); + ctx->hint_using_value = false; } void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx) { diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index 65f2d55..ae22859 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -120,40 +120,9 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder, return; } - scc_ir_type_ref_vec_t params = func_type->data.function.params; // 释放借用,因为下面要调用 add_value(可能 realloc) SCC_IR_BUILDER_END_BORROW(builder); // func_type 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) { diff --git a/libs/ir/src/ir_ctx.c b/libs/ir/src/ir_ctx.c index 9113fa2..cb2017a 100644 --- a/libs/ir/src/ir_ctx.c +++ b/libs/ir/src/ir_ctx.c @@ -11,8 +11,12 @@ static inline u32 scc_hash_mix(u32 seed, u32 value) { return (seed ^ value) * 16777619u; } -static u32 hash_type(const void *_key) { - const scc_ir_type_t *key = _key; +static u32 hash_type(const void *_key, void *userdata) { + 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 u32 hash = (u32)key->tag; @@ -65,8 +69,16 @@ static u32 hash_type(const void *_key) { return hash; } -static int cmp_type(const void *_key1, const void *_key2) { - const scc_ir_type_t *key1 = _key1, *key2 = _key2; +static int cmp_type(const void *_key1, const void *_key2, void *userdata) { + 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); if (key1->tag == SCC_IR_TYPE_unknown || key2->tag == SCC_IR_TYPE_unknown) { 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) { 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->func_decl_set, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&ctx->func_decl_set); } 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, const scc_ir_type_t *type_desc) { 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) { 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_hashtable_set(&ctx->type_uniquing, (void *)type_desc, + scc_hashtable_set(&ctx->type_uniquing, (void *)(usize)new_ref, (void *)(usize)new_ref); return new_ref; } diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index ea32fbf..bb7fad1 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -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_tree_dump_begin_line(ctx->dump_ctx); if (!func) { - scc_tree_dump_append(ctx->dump_ctx, "\n"); + scc_tree_dump_append(ctx->dump_ctx, ""); return; } scc_tree_dump_append_fmt(ctx->dump_ctx, "func @%s", diff --git a/libs/ir/src/ir_module.c b/libs/ir/src/ir_module.c index 7484d17..883064f 100644 --- a/libs/ir/src/ir_module.c +++ b/libs/ir/src/ir_module.c @@ -1,7 +1,7 @@ #include -static u32 hash_key(const void *key) { return (u32)(usize)key; } -static int cmp_key(const void *key1, const void *key2) { +static u32 hash_key(const void *key, void *userdata) { return (u32)(usize)key; } +static int cmp_key(const void *key1, const void *key2, void *userdata) { 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->bblocks); scc_vec_init(ctx->funcs); - scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key); - scc_hashtable_init(&ctx->uid2type, hash_key, cmp_key); - scc_hashtable_init(&ctx->uid2bblock, hash_key, cmp_key); - scc_hashtable_init(&ctx->uid2func, hash_key, cmp_key); + scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key, nullptr); + scc_hashtable_init(&ctx->uid2type, hash_key, cmp_key, nullptr); + scc_hashtable_init(&ctx->uid2bblock, hash_key, cmp_key, nullptr); + scc_hashtable_init(&ctx->uid2func, hash_key, cmp_key, nullptr); // 预留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->type_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) { // 释放所有实体的内部内存 - 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_vec_free(node->used_by); 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]; if (type->tag == SCC_IR_TYPE_FUNC) { 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_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_vec_free(func->params); scc_vec_free(func->bblocks); @@ -64,11 +68,11 @@ void scc_ir_module_drop(scc_ir_module_t *ctx) { do { \ /* 分配新UID */ \ unsigned new_uid = (ctx)->uid++; \ - /* 添加到向量 */ \ - scc_vec_push((vec), *(data)); \ /* 添加到哈希表 */ \ scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \ - (void *)(usize)(scc_vec_size(vec) - 1)); \ + (void *)(usize)(scc_vec_size(vec))); \ + /* 添加到向量 */ \ + scc_vec_push((vec), *(data)); \ return new_uid; \ } while (0) diff --git a/libs/ir2mcode/cbuild.toml b/libs/ir2mcode/cbuild.toml deleted file mode 100644 index b17d5ad..0000000 --- a/libs/ir2mcode/cbuild.toml +++ /dev/null @@ -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 = [] diff --git a/libs/ir2mcode/include/frame_alloc.h b/libs/ir2mcode/include/frame_alloc.h deleted file mode 100644 index 1632cb0..0000000 --- a/libs/ir2mcode/include/frame_alloc.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SCC_FRAME_ALLOC_H__ -#define __SCC_FRAME_ALLOC_H__ - -#include - -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 diff --git a/libs/ir2mcode/include/reg_alloc.h b/libs/ir2mcode/include/reg_alloc.h deleted file mode 100644 index 1d90d93..0000000 --- a/libs/ir2mcode/include/reg_alloc.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __SCC_REG_ALLOC_H__ -#define __SCC_REG_ALLOC_H__ - -#include "frame_alloc.h" -#include -#include -#include - -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__ */ diff --git a/libs/ir2mcode/include/scc_ir2mcode.h b/libs/ir2mcode/include/scc_ir2mcode.h deleted file mode 100644 index 9e1bf8b..0000000 --- a/libs/ir2mcode/include/scc_ir2mcode.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __SCC_IR2MCODE_H__ -#define __SCC_IR2MCODE_H__ - -#include "reg_alloc.h" -#include -#include -#include -#include - -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__ */ diff --git a/libs/ir2mcode/include/type_manager.h b/libs/ir2mcode/include/type_manager.h deleted file mode 100644 index 4626213..0000000 --- a/libs/ir2mcode/include/type_manager.h +++ /dev/null @@ -1,3 +0,0 @@ - -#include -int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type); diff --git a/libs/ir2mcode/src/frame_alloc_win64.c b/libs/ir2mcode/src/frame_alloc_win64.c deleted file mode 100644 index 0e38873..0000000 --- a/libs/ir2mcode/src/frame_alloc_win64.c +++ /dev/null @@ -1,159 +0,0 @@ -#include -#include -#include - -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; -} diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c deleted file mode 100644 index d33f4f4..0000000 --- a/libs/ir2mcode/src/ir2amd64.c +++ /dev/null @@ -1,786 +0,0 @@ -#include -#include -#include -#include -#include - -#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("\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); -} diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c deleted file mode 100644 index c5927a1..0000000 --- a/libs/ir2mcode/src/reg_alloc.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include - -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; - } - } - } -} diff --git a/libs/ir2mcode/src/scc_ir2mcode.c b/libs/ir2mcode/src/scc_ir2mcode.c deleted file mode 100644 index 043c13d..0000000 --- a/libs/ir2mcode/src/scc_ir2mcode.c +++ /dev/null @@ -1,19 +0,0 @@ -#include - -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); } diff --git a/libs/ir2mcode/src/type_manager.c b/libs/ir2mcode/src/type_manager.c deleted file mode 100644 index c7f1286..0000000 --- a/libs/ir2mcode/src/type_manager.c +++ /dev/null @@ -1,23 +0,0 @@ -#include - -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 */ -} diff --git a/libs/ir2mcode/tests/test_run.c b/libs/ir2mcode/tests/test_run.c deleted file mode 100644 index 041f586..0000000 --- a/libs/ir2mcode/tests/test_run.c +++ /dev/null @@ -1,110 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -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 - 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; -} diff --git a/libs/parser/src/parse_type.c b/libs/parser/src/parse_type.c index 72cfc6f..fc34254 100644 --- a/libs/parser/src/parse_type.c +++ b/libs/parser/src/parse_type.c @@ -947,9 +947,12 @@ static void parse_parameter_type_list(scc_parser_t *parser, } // TODO Check validation - param = SCC_AST_CAST_TO(scc_ast_decl_t, decl); - Assert(param->base.type = SCC_AST_DECL_VAR); - param->base.type = SCC_AST_DECL_PARAM; + param = scc_malloc(sizeof(scc_ast_decl_t)); + Assert(param != nullptr); + 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); @@ -968,7 +971,8 @@ static void parse_parameter_type_list(scc_parser_t *parser, Assert(type != nullptr); scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST, 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_vec_push(*params, param); break; diff --git a/libs/parser/src/sema_symtab.c b/libs/parser/src/sema_symtab.c index 054ab7e..06d31fa 100644 --- a/libs/parser/src/sema_symtab.c +++ b/libs/parser/src/sema_symtab.c @@ -3,9 +3,7 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) { symtab->root_scope.parent = nullptr; - scc_hashtable_init(&symtab->root_scope.symbols, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&symtab->root_scope.symbols); symtab->current_scope = &symtab->root_scope; } @@ -23,9 +21,7 @@ void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) { return; } scope->parent = symtab->current_scope; - scc_hashtable_init(&scope->symbols, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&scope->symbols); symtab->current_scope = scope; } diff --git a/libs/parser/tests/test_parse_type.c b/libs/parser/tests/test_parse_type.c index cbbd034..9c43831 100644 --- a/libs/parser/tests/test_parse_type.c +++ b/libs/parser/tests/test_parse_type.c @@ -168,7 +168,7 @@ static void test_function_type(void) { { // int (void) 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_ast_decl_vec_t params; @@ -189,9 +189,9 @@ static void test_function_type(void) { scc_pos_create()); 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_ast_decl_param_init(¶m_float, &float_type, nullptr, + scc_ast_decl_param_init(¶m_float, &float_type, nullptr, 1, scc_pos_create()); scc_ast_decl_vec_t params; @@ -213,9 +213,9 @@ static void test_function_type(void) { scc_pos_create()); 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_ast_decl_param_init(¶m_var, &va_list_type, "...", + scc_ast_decl_param_init(¶m_var, &va_list_type, "...", 1, scc_pos_create()); scc_ast_decl_vec_t params; @@ -242,7 +242,7 @@ static void test_function_type(void) { { // int (*)(void) 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_ast_decl_vec_t params; @@ -495,7 +495,7 @@ static void test_hard_type(void) { { // 1) 函数类型 int (void) 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_ast_decl_vec_t params; scc_vec_init(params); @@ -543,7 +543,7 @@ static void test_hard_type(void) { // 3) 函数类型,返回上述指针,无参数 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_ast_decl_vec_t params; scc_vec_init(params); @@ -566,7 +566,7 @@ static void test_hard_type(void) { { // 1) 函数类型 int (void) 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_ast_decl_vec_t params; scc_vec_init(params); diff --git a/libs/parser/tests/test_parse_unit.c b/libs/parser/tests/test_parse_unit.c index 0bbd8fd..9860430 100644 --- a/libs/parser/tests/test_parse_unit.c +++ b/libs/parser/tests/test_parse_unit.c @@ -43,7 +43,7 @@ static void test_parser_unit(void) { scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; 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_ast_decl_t *array[] = {&void_decl}; 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_decl_vec_t func_params; 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_ast_decl_t *array[] = {&void_decl}; 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_decl_vec_t func_params; 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_ast_decl_t *array[] = {&void_decl}; 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_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_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_ast_decl_t param2; 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_vec_unsafe_from_static_array(params, params_array); scc_ast_type_t decl_func_type; @@ -433,11 +433,11 @@ static void test_parser_unit(void) { scc_pos_create()); 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_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_param_init(¶m3, &va_list_type, nullptr, + scc_ast_decl_param_init(¶m3, &va_list_type, nullptr, 2, scc_pos_create()); scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_params; @@ -495,7 +495,7 @@ static void test_parser_unit(void) { // 2. 参数声明 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()); // 3. 返回类型:void * @@ -814,7 +814,7 @@ static void test_parser_unit(void) { scc_ast_type_t func_type; scc_ast_decl_vec_t func_params; 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_ast_decl_t *array[] = {&void_decl}; 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_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_param_init(¶m2, &typedef_func_type, "a", + scc_ast_decl_param_init(¶m2, &typedef_func_type, "a", 1, scc_pos_create()); 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_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3}; scc_ast_decl_vec_t func_hard_params; diff --git a/libs/pproc/src/pproc_macro.c b/libs/pproc/src/pproc_macro.c index 1493b6a..cddce6b 100644 --- a/libs/pproc/src/pproc_macro.c +++ b/libs/pproc/src/pproc_macro.c @@ -126,12 +126,14 @@ cbool scc_pproc_macro_table_remove(scc_pproc_macro_table_t *pp, 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; 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 *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) { 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) { diff --git a/libs/sccf/src/sccf_builder.c b/libs/sccf/src/sccf_builder.c index 6f4dc4b..5386b6c 100644 --- a/libs/sccf/src/sccf_builder.c +++ b/libs/sccf/src/sccf_builder.c @@ -3,12 +3,8 @@ void sccf_builder_init(sccf_builder_t *builder) { builder->aligned = 64; sccf_init(&builder->sccf); - scc_hashtable_init(&builder->str2offset, - (scc_hashtable_hash_func_t)scc_strhash32, - (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_hashtable_cstr_init(&builder->str2offset); + scc_hashtable_cstr_init(&builder->str2sym); scc_vec_init(builder->strtab); scc_vec_init(builder->relocs); diff --git a/libs/sstream/include/scc_sstream.h b/libs/sstream/include/scc_sstream.h index 9765b0c..4ec372a 100644 --- a/libs/sstream/include/scc_sstream.h +++ b/libs/sstream/include/scc_sstream.h @@ -1,10 +1,10 @@ #ifndef __SCC_SSTREAM_H__ #define __SCC_SSTREAM_H__ -#include "scc_pos.h" -#include "scc_pos_log.h" #include #include +#include +#include typedef struct { scc_pos_t pos; diff --git a/libs/target/pe/src/scc_pe_idata.c b/libs/target/pe/src/scc_pe_idata.c index 8a0df7c..1abab55 100644 --- a/libs/target/pe/src/scc_pe_idata.c +++ b/libs/target/pe/src/scc_pe_idata.c @@ -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) { scc_vec_init(builder->data); builder->section_offset = 0; - scc_hashtable_init(&builder->str_map, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&builder->str_map); } 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_hashtable_init(&builder->iat_map, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&builder->iat_map); } u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) { diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index 23e56a5..6422a90 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -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; usize line = 0; + // FIXME + buffer[fsize - 1] = '\0'; for (usize i = 0; i < fsize; i += 1) { if (buffer[i] == '\n') { 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) { // Got .dll.def - scc_hashtable_init(&ctx->str2libsym, - (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&ctx->str2libsym); scc_vec_init(ctx->idata_libs); ctx->find_path = find_path; load_from_def(ctx, ctx->find_path, "msvcrt.dll"); diff --git a/libs/sstream/include/scc_pos.h b/runtime/scc_core/include/scc_pos.h similarity index 100% rename from libs/sstream/include/scc_pos.h rename to runtime/scc_core/include/scc_pos.h diff --git a/runtime/scc_core/src/core_impl.c b/runtime/scc_core/src/core_impl.c index 0a8d4b7..36982dd 100644 --- a/runtime/scc_core/src/core_impl.c +++ b/runtime/scc_core/src/core_impl.c @@ -82,7 +82,6 @@ int scc_vfprintf(scc_file_t file, const char *format, va_list args) { va_list args_copy; va_copy(args_copy, args); - // 先计算所需长度 int required_size = vsnprintf_(nullptr, 0, format, 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; char *buf = nullptr; + char stack_buf[4096]; // 移到外部,作用域为整个函数 int size = 0; if (required_size < 4096) { - // 小输出使用栈上缓冲区 - char stack_buf[4096]; size = vsnprintf_(stack_buf, sizeof(stack_buf), format, args); buf = stack_buf; } else { - // 大输出使用堆分配 buf = scc_pal_malloc(required_size + 1); if (!buf) return -1; size = vsnprintf_(buf, required_size + 1, format, args); } - // 输出处理... + // 输出处理(现在 buf 始终有效) if (file == scc_stdout) { scc_pal_write(buf, size); } 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); } - // 如果使用了堆分配,释放内存 - if (buf && required_size >= 4096) { + if (required_size >= 4096 && buf) { scc_pal_free(buf); } return size; } - int scc_snprintf(char *buff, usize buff_size, const char *fmt, ...) { int ret; va_list args; diff --git a/runtime/scc_utils/include/scc_hashtable.h b/runtime/scc_utils/include/scc_hashtable.h index 466f3a3..0bc7cb5 100644 --- a/runtime/scc_utils/include/scc_hashtable.h +++ b/runtime/scc_utils/include/scc_hashtable.h @@ -33,8 +33,9 @@ typedef struct scc_hashtable_entry { scc_hashtable_entry_state_t state; /**< 当前条目状态 */ } scc_hashtable_entry_t; -typedef u32 (*scc_hashtable_hash_func_t)(const void *key); -typedef int (*scc_hashtable_equal_func_t)(const void *key1, const void *key2); +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, + void *userdata); /** * @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 { + void *userdata; SCC_VEC(scc_hashtable_entry_t) entries; /**< 条目存储容器 */ u32 count; /**< 有效条目数量(不含墓碑) */ u32 tombstone_count; /**< 墓碑条目数量 */ @@ -69,7 +71,9 @@ typedef struct scc_hashtable { */ void scc_hashtable_init(scc_hashtable_t *ht, 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 插入/更新键值对 diff --git a/libs/sstream/include/scc_pos_log.h b/runtime/scc_utils/include/scc_pos_log.h similarity index 94% rename from libs/sstream/include/scc_pos_log.h rename to runtime/scc_utils/include/scc_pos_log.h index 16a18ef..3171cf3 100644 --- a/libs/sstream/include/scc_pos_log.h +++ b/runtime/scc_utils/include/scc_pos_log.h @@ -4,7 +4,7 @@ #include "scc_pos.h" #include -extern logger_t __scc_usr_log; +extern logger_t __scc_pos_log; #define SCC_POS_LOG(level, pos, fmt, ...) \ do { \ @@ -13,7 +13,7 @@ extern logger_t __scc_usr_log; scc_pos_pnt_fmt ": ", scc_pos_pnt_val(pos)); \ scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \ ##__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); \ } while (0) diff --git a/runtime/scc_utils/src/hashtable.c b/runtime/scc_utils/src/hashtable.c index 331fea5..cad7fcc 100644 --- a/runtime/scc_utils/src/hashtable.c +++ b/runtime/scc_utils/src/hashtable.c @@ -6,16 +6,31 @@ void scc_hashtable_init(scc_hashtable_t *ht, 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); ht->count = 0; ht->tombstone_count = 0; ht->cmp_func = cmp_func; ht->hash_func = hash_func; + ht->userdata = userdata; 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) { n--; 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 (!tombstone) 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; } @@ -96,7 +112,7 @@ void *scc_hashtable_set(scc_hashtable_t *ht, const void *key, void *value) { 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); void *old_value = nullptr; @@ -119,7 +135,7 @@ void *scc_hashtable_get(scc_hashtable_t *ht, const void *key) { if (ht->entries.cap == 0) 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); 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) 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); if (entry == nullptr || entry->state != ENTRY_ACTIVE) diff --git a/libs/sstream/src/scc_pos_log.c b/runtime/scc_utils/src/scc_pos_log.c similarity index 86% rename from libs/sstream/src/scc_pos_log.c rename to runtime/scc_utils/src/scc_pos_log.c index c14504e..1f32c81 100644 --- a/libs/sstream/src/scc_pos_log.c +++ b/runtime/scc_utils/src/scc_pos_log.c @@ -1,8 +1,8 @@ #include -static int user_log_handler(logger_t *module, log_level_t level, - const char *file, int line, const char *func, - const char *fmt, ...) { +static int pos_log_handler(logger_t *module, log_level_t level, + const char *file, int line, const char *func, + const char *fmt, ...) { /* clang-format off */ (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; } -logger_t __scc_usr_log = { - .name = "user", - .handler = user_log_handler, +logger_t __scc_pos_log = { + .name = "pos_log", + .handler = pos_log_handler, .level = LOG_LEVEL_ALL, }; diff --git a/runtime/scc_utils/src/strpool.c b/runtime/scc_utils/src/strpool.c index 780d54a..3b9ed53 100644 --- a/runtime/scc_utils/src/strpool.c +++ b/runtime/scc_utils/src/strpool.c @@ -1,8 +1,7 @@ #include void scc_strpool_init(scc_strpool_t *pool) { - scc_hashtable_init(&pool->ht, (scc_hashtable_hash_func_t)scc_strhash32, - (scc_hashtable_equal_func_t)scc_strcmp); + scc_hashtable_cstr_init(&pool->ht); } const char *scc_strpool_intern(scc_strpool_t *pool, const char *str) { diff --git a/src/init.c b/src/init.c index 2eb07a7..9aebba8 100644 --- a/src/init.c +++ b/src/init.c @@ -1,10 +1,86 @@ +#include + #ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include +#include +#include +/// Ddghelp.h 必须在 Windows.h 后定义 +#include + +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 void init_platform(void) { #ifdef _WIN32 + signal(SIGABRT, SignalHandler); +#ifdef DEV_MODE + SetUnhandledExceptionFilter(CreateMiniDump); +#endif SetConsoleOutputCP(CP_UTF8); SetConsoleCP(CP_UTF8); #endif diff --git a/src/main.c b/src/main.c index c4956ac..a19912c 100644 --- a/src/main.c +++ b/src/main.c @@ -155,6 +155,7 @@ int main(int argc, const char **argv, const char **envp) { scc_str_t pproc_predefined_macros[] = { scc_str_from_cstr("__SCC__"), scc_str_from_cstr("_WIN64"), + scc_str_from_cstr("_WIN32"), scc_str_from_cstr("__x86_64__"), }; for (usize i = 0; i < SCC_ARRLEN(pproc_predefined_macros); i += 1) {