diff --git a/cbuild.toml b/cbuild.toml index 4be8207..9ef074a 100644 --- a/cbuild.toml +++ b/cbuild.toml @@ -10,7 +10,8 @@ dependencies = [ { name = "ast", path = "./libs/ast" }, { name = "ast2ir", path = "./libs/ast2ir" }, { name = "ir", path = "./libs/ir" }, + { name = "lir", path = "./libs/lir" }, - { name = "ir2mcode", path = "./libs/ir2mcode" }, - { name = "sccf2target", path = "./libs/target/sccf2target" }, + # { name = "ir2mcode", path = "./libs/ir2mcode" }, + # { name = "sccf2target", path = "./libs/target/sccf2target" }, ] diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 85a3e36..af75a61 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -8,7 +8,7 @@ static scc_ir_type_ref_t parse_base_type(scc_ast2ir_ctx_t *ctx, const scc_ast_type_t *ast_type) { scc_abi_type_layout_t layout; // 映射内置类型 - ctx->abi->compute_type_layout(ctx->abi, ast_type, &layout); + ctx->abi->compute_type_layout(ctx->abi, (void *)ast_type, &layout); switch (layout.size) { case 0: return scc_ir_builder_type_void(&ctx->builder); @@ -668,6 +668,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, LOG_FATAL("Unsupported expression type: %d", expr->base.type); return 0; } + UNREACHABLE(); } /** @@ -942,7 +943,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl, break; } - scc_ir_builder_begin_func(&ctx->builder, func_ref, nullptr); + scc_ir_builder_begin_func(&ctx->builder, func_ref); scc_ir_builder_begin_bblock(&ctx->builder, "entry"); scc_vec_foreach(decl->func.type->function.params, i) { @@ -1033,20 +1034,12 @@ void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, } } -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; -} - void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi, scc_ir_cprog_t *cprog) { 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, - nullptr); + scc_hashtable_usize_init(&ctx->ast2ir_cache); scc_hashtable_cstr_init(&ctx->symtab); ctx->hint_using_value = false; } diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index 2105033..6d03e76 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -153,8 +153,7 @@ scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder, * @return void */ void scc_ir_builder_begin_func(scc_ir_builder_t *builder, - scc_ir_func_ref_t func_ref, - const char **param_names); + scc_ir_func_ref_t func_ref); /** * @brief 结束当前函数的构建 diff --git a/libs/ir/src/ir_builder.c b/libs/ir/src/ir_builder.c index ae22859..fd84a56 100644 --- a/libs/ir/src/ir_builder.c +++ b/libs/ir/src/ir_builder.c @@ -85,8 +85,7 @@ scc_ir_value_ref_t scc_ir_builder_const_string(scc_ir_builder_t *builder, } void scc_ir_builder_begin_func(scc_ir_builder_t *builder, - scc_ir_func_ref_t func_ref, - const char **param_names) { + scc_ir_func_ref_t func_ref) { SCC_IR_BUILDER_CHECK_NO_BORROW(builder); builder->current_func = func_ref; @@ -480,7 +479,12 @@ scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) { SCC_IR_BUILDER_CHECK_NO_BORROW(builder); scc_ir_value_t ret_node = {0}; ret_node.tag = SCC_IR_VALUE_TAG_RET; - ret_node.data.ret.ret_val = 0; + + scc_ir_value_t ret_val_node; + scc_ir_value_init(&ret_val_node, nullptr, SCC_IR_VALUE_TAG_NULLPTR); + ret_val_node.type = scc_ir_builder_type_void(builder); + ret_node.data.ret.ret_val = + scc_ir_module_add_value(GET_MODULE(builder), &ret_val_node); scc_ir_value_ref_t value_ref = scc_ir_module_add_value(GET_MODULE(builder), &ret_node); diff --git a/libs/ir/src/ir_module.c b/libs/ir/src/ir_module.c index 883064f..ac38f61 100644 --- a/libs/ir/src/ir_module.c +++ b/libs/ir/src/ir_module.c @@ -1,19 +1,14 @@ #include -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; -} - void scc_ir_module_init(scc_ir_module_t *ctx) { scc_vec_init(ctx->values); scc_vec_init(ctx->types); scc_vec_init(ctx->bblocks); scc_vec_init(ctx->funcs); - scc_hashtable_init(&ctx->uid2value, hash_key, cmp_key, 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); + scc_hashtable_usize_init(&ctx->uid2value); + scc_hashtable_usize_init(&ctx->uid2type); + scc_hashtable_usize_init(&ctx->uid2bblock); + scc_hashtable_usize_init(&ctx->uid2func); // 预留UID 0 作为无效引用 scc_vec_push(ctx->values, (scc_ir_value_t){0}); scc_vec_push(ctx->types, (scc_ir_type_t){0}); diff --git a/libs/lir/cbuild.toml b/libs/lir/cbuild.toml new file mode 100644 index 0000000..796dfcb --- /dev/null +++ b/libs/lir/cbuild.toml @@ -0,0 +1,13 @@ +[package] +name = "scc_lir" +version = "0.1.0" +authors = [] +description = "" + +dependencies = [ + { name = "scc_ir", path = "../ir" }, + { name = "scc_utils", path = "../../runtime/scc_utils" }, + { name = "tree_dump", path = "../tree_dump" }, +] +# features = {} +# default_features = [] diff --git a/libs/lir/include/scc_ir2lir.h b/libs/lir/include/scc_ir2lir.h new file mode 100644 index 0000000..8d6c6de --- /dev/null +++ b/libs/lir/include/scc_ir2lir.h @@ -0,0 +1,12 @@ +#ifndef __SCC_IR2LIR_H__ +#define __SCC_IR2LIR_H__ + +#include "scc_lir.h" +#include "scc_lir_builder.h" +#include "scc_lir_module.h" +#include + +scc_lir_module_t *scc_ir2lir(scc_lir_builder_t *builder, + const scc_ir_cprog_t *cprog); + +#endif /* __SCC_IR2LIR_H__ */ diff --git a/libs/lir/include/scc_lir.h b/libs/lir/include/scc_lir.h new file mode 100644 index 0000000..c963eee --- /dev/null +++ b/libs/lir/include/scc_lir.h @@ -0,0 +1,263 @@ +/** + * @file scc_lir.h + * @brief 低层中间表示 (Low-Level IR) - 实用精简版 + * + * 设计原则: + * - 依赖 scc_core.h 和 scc_utils.h (仅使用哈希表) + * - 保留所有核心功能:复杂地址、并行复制、VA 支持、符号引用 + * - 基本块使用稳定 ID,通过哈希表快速查找 + * - 预留属性位掩码 (attr),未来可扩展 align、packed、weak 等 + * - 无字符串池、无类型缓存,保持简单 + */ + +#ifndef __SCC_LIR_H__ +#define __SCC_LIR_H__ + +#include +#include +#include + +typedef enum scc_lir_attr { + SCC_LIR_ATTR_NONE = 0, + SCC_LIR_ATTR_STATIC = 1 << 0, // 内部链接 + SCC_LIR_ATTR_WEAK = 1 << 1, // 弱符号 + SCC_LIR_ATTR_VIS_HIDDEN = 1 << 2, // 符号可见性 hidden + SCC_LIR_ATTR_NOINLINE = 1 << 3, + SCC_LIR_ATTR_ALWAYSINLINE = 1 << 4, + // 对齐值可编码在 attr 的高位,例如: + // #define SCC_LIR_ATTR_ALIGN(n) (((n) << 8) | SCC_LIR_ATTR_ALIGN_FLAG) +} scc_lir_attr_t; + +typedef enum { + SCC_LIR_INSTR_KIND_NONE, // 无操作数 + SCC_LIR_INSTR_KIND_VREG, // 虚拟寄存器 + SCC_LIR_INSTR_KIND_PREG, // 物理寄存器 (后端定义编号) + SCC_LIR_INSTR_KIND_IMM, // 整数立即数 + SCC_LIR_INSTR_KIND_FIMM, // 浮点立即数 + SCC_LIR_INSTR_KIND_SYMBOL, // 全局符号 (函数名、全局变量、字符串常量) + SCC_LIR_INSTR_KIND_ADDR // 复杂地址表达式 (base + index*scale + offset) +} scc_lir_instr_kind_t; + +/** + * @brief 复杂地址表达式 + * base + index * scale + offset + */ +typedef struct scc_lir_addr { + int base; // 基址寄存器,-1 表示无 + int index; // 索引寄存器,-1 表示无 + int scale; // 比例因子 (1, 2, 4, 8) + i64 offset; // 常量偏移 +} scc_lir_addr_t; + +typedef struct scc_lir_instr { + scc_lir_instr_kind_t kind; + union { + unsigned int reg; // VREG 或 PREG 索引 + i64 imm; // 整型立即数 + f64 fimm; // 浮点立即数 + const char *symbol; // 符号名 (生命周期由前端管理) + scc_lir_addr_t addr; // 复杂地址 + } data; +} scc_lir_val_t; + +/* 构造宏 */ +#define SCC_LIR_NONE() ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_NONE}) +#define SCC_LIR_VREG(n) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_VREG, .data.reg = (n)}) +#define SCC_LIR_PREG(r) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_PREG, .data.reg = (r)}) +#define SCC_LIR_IMM(v) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_IMM, .data.imm = (v)}) +#define SCC_LIR_FIMM(v) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_FIMM, .data.fimm = (v)}) +#define SCC_LIR_SYMBOL(s) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_SYMBOL, .data.symbol = (s)}) +#define SCC_LIR_ADDR(b, i, s, o) \ + ((scc_lir_val_t){.kind = SCC_LIR_INSTR_KIND_ADDR, \ + .data.addr = {b, i, s, o}}) + +#define SCC_LIR_SIZE_8 1 +#define SCC_LIR_SIZE_16 2 +#define SCC_LIR_SIZE_32 4 +#define SCC_LIR_SIZE_64 8 + +typedef enum { + SCC_LIR_EXT_NONE, + SCC_LIR_EXT_SEXT, + SCC_LIR_EXT_ZEXT, + SCC_LIR_EXT_FLOAT +} scc_lir_ext_t; + +typedef enum { + /* 数据移动 */ + SCC_LIR_MOV, + SCC_LIR_LOAD, + SCC_LIR_LOAD_ADDR, + SCC_LIR_STORE, + SCC_LIR_STORE_ADDR, + SCC_LIR_LEA, + + /* 整数算术 */ + SCC_LIR_ADD, + SCC_LIR_SUB, + SCC_LIR_MUL, + SCC_LIR_DIV_S, + SCC_LIR_DIV_U, + SCC_LIR_REM_S, + SCC_LIR_REM_U, + SCC_LIR_AND, + SCC_LIR_OR, + SCC_LIR_XOR, + SCC_LIR_SHL, + SCC_LIR_SHR, + SCC_LIR_SAR, + SCC_LIR_NEG, + SCC_LIR_NOT, + + /* 浮点算术 */ + SCC_LIR_FADD, + SCC_LIR_FSUB, + SCC_LIR_FMUL, + SCC_LIR_FDIV, + SCC_LIR_FNEG, + SCC_LIR_FCVT, + + /* 比较 */ + SCC_LIR_CMP, + + /* 控制流 */ + SCC_LIR_BR, + SCC_LIR_JMP, + SCC_LIR_JMP_INDIRECT, + SCC_LIR_CALL, + SCC_LIR_CALL_INDIRECT, + SCC_LIR_RET, + + /* 并行复制 */ + SCC_LIR_PARALLEL_COPY, + + /* 可变参数 */ + SCC_LIR_VA_START, + SCC_LIR_VA_ARG, + SCC_LIR_VA_END, + SCC_LIR_VA_COPY, + + /* 栈管理 */ + SCC_LIR_ALLOCA, + + SCC_LIR_NOP +} scc_lir_op_t; + +typedef enum { + SCC_LIR_COND_EQ, + SCC_LIR_COND_NE, + SCC_LIR_COND_SLT, + SCC_LIR_COND_SLE, + SCC_LIR_COND_SGT, + SCC_LIR_COND_SGE, + SCC_LIR_COND_ULT, + SCC_LIR_COND_ULE, + SCC_LIR_COND_UGT, + SCC_LIR_COND_UGE, + SCC_LIR_COND_FEQ, + SCC_LIR_COND_FNE, + SCC_LIR_COND_FLT, + SCC_LIR_COND_FLE, + SCC_LIR_COND_FGT, + SCC_LIR_COND_FGE +} scc_lir_cond_t; + +typedef usize scc_lir_bblock_uid_t; + +typedef struct scc_lir_ins { + scc_lir_op_t op; + u8 size; + scc_lir_ext_t ext; + scc_lir_val_t to; + scc_lir_val_t arg0; + scc_lir_val_t arg1; + /// @brief debug 信息 + scc_pos_t src_loc; + + union { + scc_lir_cond_t cond; + + struct scc_lir_br { + scc_lir_bblock_uid_t true_target; + scc_lir_bblock_uid_t false_target; + } br; + + scc_lir_bblock_uid_t jmp_target; + + struct scc_lir_call { + const char *callee; + scc_lir_val_t *args; + int arg_count; + scc_lir_val_t ret_vreg; + u64 clobber_mask; + } call; + + struct scc_lir_call_indirect { + scc_lir_val_t target; + scc_lir_val_t *args; + int arg_count; + scc_lir_val_t ret_vreg; + u64 clobber_mask; + } call_indirect; + + scc_lir_val_t ret_val; + + struct scc_lir_parallel_copy { + scc_lir_val_t *dests; + scc_lir_val_t *srcs; + int num_copies; + } parallel_copy; + + struct scc_lir_alloca { + int size_bytes; + int align_bytes; + } alloca; + + struct { + scc_lir_val_t ap; + scc_lir_val_t last; + } va_start; + + struct { + scc_lir_val_t ap; + int type_size; + int type_align; + char is_float; + scc_lir_val_t to; + } va_arg; + + struct { + scc_lir_val_t ap; + } va_end; + + struct { + scc_lir_val_t dest; + scc_lir_val_t src; + } va_copy; + } metadata; +} scc_lir_instr_t; + +typedef SCC_VEC(scc_lir_instr_t) scc_lir_instr_vec_t; +typedef struct scc_lir_bblock { + scc_lir_bblock_uid_t id; // 稳定唯一 ID + const char *label; // 可读标签 + scc_lir_instr_vec_t ins; // 指令序列 +} scc_lir_bblock_t; + +typedef SCC_VEC(scc_lir_bblock_t) scc_lir_bblock_vec_t; +typedef struct scc_lir_func { + const char *name; + scc_lir_bblock_vec_t bblocks; + scc_hashtable_t bb_map; // ID -> 基本块索引 (usize) + scc_lir_bblock_uid_t next_bb_uid; + unsigned int vregs_count; + int frame_size; + scc_lir_attr_t attr; +} scc_lir_func_t; + +#endif /* __SCC_LIR_H__ */ diff --git a/libs/lir/include/scc_lir_builder.h b/libs/lir/include/scc_lir_builder.h new file mode 100644 index 0000000..229e6d2 --- /dev/null +++ b/libs/lir/include/scc_lir_builder.h @@ -0,0 +1,26 @@ +#ifndef __SCC_LIR_BUILDER_H__ +#define __SCC_LIR_BUILDER_H__ + +#include "scc_lir.h" +#include "scc_lir_module.h" +#include + +typedef struct scc_lir_builder { + scc_lir_func_t *func; + scc_lir_bblock_t *cur_bb; + scc_hashtable_t value_to_vreg; // 高层 IR 值 -> 虚拟寄存器 + scc_lir_module_t *module; +} scc_lir_builder_t; + +void scc_lir_builder_init(scc_lir_builder_t *builder, scc_lir_module_t *module); +void scc_lir_builder_drop(scc_lir_builder_t *builder); +void scc_lir_builder_begin_func(scc_lir_builder_t *builder, const char *name); +void scc_lir_builder_end_func(scc_lir_builder_t *builder); +void scc_lir_builder_begin_bblock(scc_lir_builder_t *builder, + const char *label); +void scc_lir_builder_end_bblock(scc_lir_builder_t *builder); +void scc_lir_builder_add_instr(scc_lir_builder_t *builder, + const scc_lir_instr_t *instr); +unsigned int scc_lir_builder_new_vreg(scc_lir_builder_t *builder); + +#endif /* __SCC_LIR_BUILDER_H__ */ diff --git a/libs/lir/include/scc_lir_dump.h b/libs/lir/include/scc_lir_dump.h new file mode 100644 index 0000000..86b8a6d --- /dev/null +++ b/libs/lir/include/scc_lir_dump.h @@ -0,0 +1,22 @@ +#ifndef __SCC_LIR_DUMP_H__ +#define __SCC_LIR_DUMP_H__ + +#include "scc_lir.h" +#include "scc_lir_module.h" +#include + +typedef struct { + scc_tree_dump_t *dump_ctx; +} scc_lir_dump_ctx_t; + +static inline void scc_lir_dump_init(scc_lir_dump_ctx_t *ctx, + scc_tree_dump_t *dump_ctx) { + ctx->dump_ctx = dump_ctx; +} +void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins); +void scc_lir_dump_bblock(scc_lir_dump_ctx_t *ctx, const scc_lir_bblock_t *bb); +void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func); +void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx, + const scc_lir_module_t *module); + +#endif /* __SCC_LIR_DUMP_H__ */ diff --git a/libs/lir/include/scc_lir_module.h b/libs/lir/include/scc_lir_module.h new file mode 100644 index 0000000..ed91b8e --- /dev/null +++ b/libs/lir/include/scc_lir_module.h @@ -0,0 +1,98 @@ +/** + * @file scc_lir_module.h + * @brief LIR 模块:管理函数定义、全局符号和声明 + */ + +#ifndef __SCC_LIR_MODULE_H__ +#define __SCC_LIR_MODULE_H__ + +#include "scc_lir.h" +#include +#include + +typedef enum scc_lir_symbol_kind { + SCC_LIR_SYMBOL_FUNC, // 函数符号 + SCC_LIR_SYMBOL_DATA, // 数据符号(全局变量、常量) + SCC_LIR_SYMBOL_EXTERN, // 外部符号(未定义,需链接器解析) +} scc_lir_symbol_kind_t; + +typedef struct scc_lir_symbol { + const char *name; // 符号名(驻留字符串或前端管理) + scc_lir_symbol_kind_t kind; // 符号类型 + scc_lir_attr_t attr; // 属性(static, weak 等) + + union { + struct { + scc_lir_func_t *func; // 指向函数体(若为定义) + } func; + struct { + u8 *init_data; // 初始化数据(若为 NULL 则零初始化) + usize size; // 数据大小(字节) + int align; // 对齐要求 + } data; + }; +} scc_lir_symbol_t; + +typedef struct scc_lir_module { + SCC_VEC(scc_lir_func_t *) funcs; // 所有函数定义(按添加顺序) + SCC_VEC(scc_lir_symbol_t) symbols; // 所有全局符号(包含声明和定义) + scc_hashtable_t symbol_map; // name -> 索引 (usize) 在 symbols 向量中 +} scc_lir_module_t; + +/** + * @brief 初始化 LIR 模块 + */ +void scc_lir_module_init(scc_lir_module_t *module); + +/** + * @brief 销毁 LIR 模块,释放所有函数和符号资源 + */ +void scc_lir_module_drop(scc_lir_module_t *module); + +/** + * @brief 添加一个函数定义到模块 + * @param mod 模块 + * @param func 函数定义(所有权转移给模块) + * @return 符号指针(内部持有,不可释放) + */ +const scc_lir_symbol_t *scc_lir_module_add_func_def(scc_lir_module_t *module, + scc_lir_func_t *func); + +/** + * @brief 添加一个函数声明(外部或未定义) + * @param mod 模块 + * @param name 函数名 + * @param attr 属性 + * @return 符号指针 + */ +const scc_lir_symbol_t *scc_lir_module_add_func_decl(scc_lir_module_t *module, + const char *name, + scc_lir_attr_t attr); + +/** + * @brief 添加一个全局数据符号(定义或外部) + * @param mod 模块 + * @param name 符号名 + * @param kind 种类(DATA 或 EXTERN) + * @param init_data 初始化数据(若为 DATA 定义;若为 NULL 则零初始化) + * @param size 数据大小(若为 EXTERN 可为 0) + * @param align 对齐要求 + * @param attr 属性 + * @return 符号指针 + */ +const scc_lir_symbol_t *scc_lir_module_add_data(scc_lir_module_t *module, + const char *name, + scc_lir_symbol_kind_t kind, + const u8 *init_data, usize size, + u32 align, scc_lir_attr_t attr); + +/** + * @brief 通过名称查找符号 + * @param mod 模块 + * @param name 符号名 + * @return 符号指针,未找到返回 nullptr + */ +const scc_lir_symbol_t * +scc_lir_module_lookup_symbol(const scc_lir_module_t *module, const char *name); + +#endif /* __SCC_LIR_MODULE_H__ */ diff --git a/libs/lir/src/scc_ir2lir.c b/libs/lir/src/scc_ir2lir.c new file mode 100644 index 0000000..5d09996 --- /dev/null +++ b/libs/lir/src/scc_ir2lir.c @@ -0,0 +1,599 @@ +/** + * @file scc_ir2lir.c + * @brief 将高级 IR (scc_ir) 降级为低层 LIR (scc_lir) + */ + +#include +#include + +/* ---------- 转换上下文 ---------- */ +typedef struct { + scc_lir_builder_t *builder; + scc_ir_module_t *ir_module; + scc_hashtable_t bb_map; // ir_bblock_ref_t -> scc_lir_bblock_uid_t + scc_hashtable_t value_to_vreg; // ir_value_ref_t -> unsigned int vreg + scc_hashtable_t func_decl_map; // ir_func_ref_t -> const char* (用于调用) +} ir2lir_ctx_t; + +static void ir2lir_ctx_init(ir2lir_ctx_t *ctx, scc_lir_builder_t *builder, + scc_ir_module_t *ir_module) { + ctx->builder = builder; + ctx->ir_module = ir_module; + scc_hashtable_usize_init(&ctx->bb_map); + scc_hashtable_usize_init(&ctx->value_to_vreg); + scc_hashtable_usize_init(&ctx->func_decl_map); +} + +static void ir2lir_ctx_drop(ir2lir_ctx_t *ctx) { + scc_hashtable_drop(&ctx->bb_map); + scc_hashtable_drop(&ctx->value_to_vreg); + scc_hashtable_drop(&ctx->func_decl_map); +} + +/* ---------- 工具函数 ---------- */ + +// 获取 IR 类型对应的 LIR 大小和扩展属性 +static void ir_type_to_lir_size_ext(scc_ir_type_t *type, u8 *out_size, + scc_lir_ext_t *out_ext) { + switch (type->tag) { + case SCC_IR_TYPE_i8: + *out_size = SCC_LIR_SIZE_8; + *out_ext = SCC_LIR_EXT_SEXT; + break; + case SCC_IR_TYPE_u8: + *out_size = SCC_LIR_SIZE_8; + *out_ext = SCC_LIR_EXT_ZEXT; + break; + case SCC_IR_TYPE_i16: + *out_size = SCC_LIR_SIZE_16; + *out_ext = SCC_LIR_EXT_SEXT; + break; + case SCC_IR_TYPE_u16: + *out_size = SCC_LIR_SIZE_16; + *out_ext = SCC_LIR_EXT_ZEXT; + break; + case SCC_IR_TYPE_i32: + *out_size = SCC_LIR_SIZE_32; + *out_ext = SCC_LIR_EXT_SEXT; + break; + case SCC_IR_TYPE_u32: + *out_size = SCC_LIR_SIZE_32; + *out_ext = SCC_LIR_EXT_ZEXT; + break; + case SCC_IR_TYPE_i64: + *out_size = SCC_LIR_SIZE_64; + *out_ext = SCC_LIR_EXT_SEXT; + break; + case SCC_IR_TYPE_u64: + *out_size = SCC_LIR_SIZE_64; + *out_ext = SCC_LIR_EXT_ZEXT; + break; + case SCC_IR_TYPE_f32: + *out_size = SCC_LIR_SIZE_32; + *out_ext = SCC_LIR_EXT_FLOAT; + break; + case SCC_IR_TYPE_f64: + *out_size = SCC_LIR_SIZE_64; + *out_ext = SCC_LIR_EXT_FLOAT; + break; + case SCC_IR_TYPE_PTR: + *out_size = SCC_LIR_SIZE_64; + *out_ext = SCC_LIR_EXT_NONE; + break; + case SCC_IR_TYPE_void: + *out_size = 0; + *out_ext = SCC_LIR_EXT_NONE; + break; + default: + Panic("unsupported IR type in lowering"); + } +} + +// 获取或创建 IR 值对应的虚拟寄存器 +static unsigned int get_vreg_for_value(ir2lir_ctx_t *ctx, + scc_ir_value_ref_t val_ref) { + void *found = + scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)val_ref); + if (found) + return (unsigned int)(uintptr_t)found; + + unsigned int vreg = scc_lir_builder_new_vreg(ctx->builder); + scc_hashtable_set(&ctx->value_to_vreg, (void *)(uintptr_t)val_ref, + (void *)(uintptr_t)vreg); + return vreg; +} + +// 将 IR 值转换为 LIR 操作数 (可能递归触发指令生成) +static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx, + scc_ir_value_ref_t val_ref); + +// 前向声明 +static void translate_ir_value(ir2lir_ctx_t *ctx, scc_ir_value_t *value, + scc_ir_value_ref_t value_ref); + +// 获取 LIR 操作数:若为常量/全局符号则直接构造,否则返回对应 vreg +static scc_lir_val_t ir_value_to_lir_operand(ir2lir_ctx_t *ctx, + scc_ir_value_ref_t val_ref) { + scc_ir_value_t *val = scc_ir_module_get_value(ctx->ir_module, val_ref); + Assert(val != nullptr); + + switch (val->tag) { + case SCC_IR_VALUE_TAG_CONST_INT: { + scc_ir_type_t *ty = scc_ir_module_get_type(ctx->ir_module, val->type); + i64 imm = 0; + if (ty->tag == SCC_IR_TYPE_i8 || ty->tag == SCC_IR_TYPE_u8) + imm = val->data.const_int.int8; + else if (ty->tag == SCC_IR_TYPE_i16 || ty->tag == SCC_IR_TYPE_u16) + imm = val->data.const_int.int16; + else if (ty->tag == SCC_IR_TYPE_i32 || ty->tag == SCC_IR_TYPE_u32) + imm = val->data.const_int.int32; + else if (ty->tag == SCC_IR_TYPE_i64 || ty->tag == SCC_IR_TYPE_u64) + imm = val->data.const_int.int64; + else + imm = val->data.const_int.int64; + return SCC_LIR_IMM(imm); + } + case SCC_IR_VALUE_TAG_CONST_FLOAT: { + scc_ir_type_t *ty = scc_ir_module_get_type(ctx->ir_module, val->type); + f64 fimm = (ty->tag == SCC_IR_TYPE_f32) ? val->data.const_float.float32 + : val->data.const_float.float64; + return SCC_LIR_FIMM(fimm); + } + case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: { + // 全局变量地址作为符号 + scc_ir_value_t *global_val = scc_ir_module_get_value( + ctx->ir_module, val->data.global_alloc.value); + return SCC_LIR_SYMBOL(global_val->name); + } + case SCC_IR_VALUE_TAG_FUNC_ARG_REF: { + // 函数参数:预先已分配 vreg + unsigned int vreg = get_vreg_for_value(ctx, val_ref); + return SCC_LIR_VREG(vreg); + } + case SCC_IR_VALUE_TAG_NULLPTR: { + return SCC_LIR_IMM(0); + } + default: { + // 其他所有产生值的指令:确保其指令已生成,然后返回 vreg + // 注意:这里可能会递归调用 translate_ir_value,因此需要先检查是否已翻译 + void *found = + scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)val_ref); + if (!found) { + translate_ir_value(ctx, val, val_ref); + } + unsigned int vreg = (unsigned int)(uintptr_t)scc_hashtable_get( + &ctx->value_to_vreg, (void *)(uintptr_t)val_ref); + return SCC_LIR_VREG(vreg); + } + } +} + +/* ---------- 操作码映射 ---------- */ + +static scc_lir_cond_t map_cmp_cond(scc_ir_op_type_t op, cbool is_float) { + if (is_float) { + switch (op) { + case SCC_IR_OP_EQ: + return SCC_LIR_COND_FEQ; + case SCC_IR_OP_NEQ: + return SCC_LIR_COND_FNE; + case SCC_IR_OP_LT: + return SCC_LIR_COND_FLT; + case SCC_IR_OP_LE: + return SCC_LIR_COND_FLE; + case SCC_IR_OP_GT: + return SCC_LIR_COND_FGT; + case SCC_IR_OP_GE: + return SCC_LIR_COND_FGE; + default: + Panic("invalid float cmp"); + } + } else { + // 默认为有符号比较 (无符号需额外处理类型) + switch (op) { + case SCC_IR_OP_EQ: + return SCC_LIR_COND_EQ; + case SCC_IR_OP_NEQ: + return SCC_LIR_COND_NE; + case SCC_IR_OP_LT: + return SCC_LIR_COND_SLT; + case SCC_IR_OP_LE: + return SCC_LIR_COND_SLE; + case SCC_IR_OP_GT: + return SCC_LIR_COND_SGT; + case SCC_IR_OP_GE: + return SCC_LIR_COND_SGE; + default: + Panic("invalid int cmp"); + } + } + return SCC_LIR_COND_EQ; +} + +static scc_lir_op_t map_binop(scc_ir_op_type_t op, bool is_float) { + if (is_float) { + switch (op) { + case SCC_IR_OP_ADD: + return SCC_LIR_FADD; + case SCC_IR_OP_SUB: + return SCC_LIR_FSUB; + case SCC_IR_OP_MUL: + return SCC_LIR_FMUL; + case SCC_IR_OP_DIV: + return SCC_LIR_FDIV; + default: + Panic("unsupported float binop"); + } + } else { + switch (op) { + case SCC_IR_OP_ADD: + return SCC_LIR_ADD; + case SCC_IR_OP_SUB: + return SCC_LIR_SUB; + case SCC_IR_OP_MUL: + return SCC_LIR_MUL; + case SCC_IR_OP_DIV: + return SCC_LIR_DIV_S; + case SCC_IR_OP_MOD: + return SCC_LIR_REM_S; + case SCC_IR_OP_AND: + return SCC_LIR_AND; + case SCC_IR_OP_OR: + return SCC_LIR_OR; + case SCC_IR_OP_XOR: + return SCC_LIR_XOR; + case SCC_IR_OP_SHL: + return SCC_LIR_SHL; + case SCC_IR_OP_SHR: + return SCC_LIR_SHR; + case SCC_IR_OP_SAR: + return SCC_LIR_SAR; + default: + return map_cmp_cond(op, is_float); + } + } + return SCC_LIR_NOP; +} + +/* ---------- 单条 IR 指令翻译 ---------- */ + +static void translate_ir_value(ir2lir_ctx_t *ctx, scc_ir_value_t *value, + scc_ir_value_ref_t value_ref) { + // 防止重复翻译 + if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref)) + return; + + scc_ir_type_t *ty = scc_ir_module_get_type(ctx->ir_module, value->type); + u8 size = 0; + scc_lir_ext_t ext = SCC_LIR_EXT_NONE; + if (ty != nullptr) { + ir_type_to_lir_size_ext(ty, &size, &ext); + } + bool is_float = (ext == SCC_LIR_EXT_FLOAT); + + // 为当前指令分配目标虚拟寄存器 + unsigned int dst_vreg = get_vreg_for_value(ctx, value_ref); + + switch (value->tag) { + case SCC_IR_VALUE_TAG_OP: { + scc_lir_val_t lhs = ir_value_to_lir_operand(ctx, value->data.op.lhs); + scc_lir_val_t rhs = ir_value_to_lir_operand(ctx, value->data.op.rhs); + scc_lir_op_t op = map_binop(value->data.op.op, is_float); + + scc_lir_instr_t instr = {.op = op, + .size = size, + .ext = ext, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = lhs, + .arg1 = rhs}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_LOAD: { + scc_lir_val_t addr = + ir_value_to_lir_operand(ctx, value->data.load.target); + scc_lir_instr_t instr = {.op = SCC_LIR_LOAD, + .size = size, + .ext = ext, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = addr}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_STORE: { + scc_lir_val_t data = + ir_value_to_lir_operand(ctx, value->data.store.value); + scc_lir_val_t addr = + ir_value_to_lir_operand(ctx, value->data.store.target); + scc_lir_instr_t instr = { + .op = SCC_LIR_STORE, .size = size, .arg0 = data, .arg1 = addr}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: { + // 将指针运算转换为 LEA + scc_lir_val_t base = + ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.src_addr); + scc_lir_val_t index = SCC_LIR_IMM(0); + if (value->data.get_elem_ptr.index) + ir_value_to_lir_operand(ctx, value->data.get_elem_ptr.index); + + // 计算元素大小 + scc_ir_type_t *ptr_ty = scc_ir_module_get_type_by_value( + ctx->ir_module, value->data.get_elem_ptr.src_addr); + scc_ir_type_t *elem_ty = nullptr; + if (ptr_ty->tag == SCC_IR_TYPE_PTR) { + elem_ty = scc_ir_module_get_type(ctx->ir_module, + ptr_ty->data.pointer.base); + } else if (ptr_ty->tag == SCC_IR_TYPE_ARRAY) { + elem_ty = + scc_ir_module_get_type(ctx->ir_module, ptr_ty->data.array.base); + } + Assert(elem_ty != nullptr); + int elem_size = 0; + // 简化:仅处理基本类型 + if (elem_ty->tag == SCC_IR_TYPE_i32 || elem_ty->tag == SCC_IR_TYPE_u32) + elem_size = 4; + else if (elem_ty->tag == SCC_IR_TYPE_i64 || + elem_ty->tag == SCC_IR_TYPE_u64) + elem_size = 8; + else if (elem_ty->tag == SCC_IR_TYPE_i8 || + elem_ty->tag == SCC_IR_TYPE_u8) + elem_size = 1; + else if (elem_ty->tag == SCC_IR_TYPE_ARRAY) + elem_size = 8; // FIXME ptr size + else + Panic("unsupported element type for getelemptr"); + + // 构造地址表达式:base + index * elem_size + scc_lir_val_t addr = + SCC_LIR_ADDR(dst_vreg, -1, index.data.reg, elem_size); + // 更简单的做法:使用 LEA 指令,参数为 base 和 index,由后端展开 + scc_lir_instr_t instr = {.op = SCC_LIR_LEA, + .size = SCC_LIR_SIZE_64, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = base, + .arg1 = index}; + // 实际需要将 index * elem_size 的信息编码,这里简化,假设后端处理 + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_ALLOC: { + // alloca 指令:分配栈空间 + scc_ir_type_t *alloc_ty = + scc_ir_module_get_type(ctx->ir_module, ty->data.pointer.base); + // 计算大小和对齐(简化) + int alloc_size = 8; // 默认 + if (alloc_ty->tag == SCC_IR_TYPE_i32) + alloc_size = 4; + scc_lir_instr_t instr = {.op = SCC_LIR_ALLOCA, + .size = SCC_LIR_SIZE_64, + .to = SCC_LIR_VREG(dst_vreg), + .metadata.alloca = {alloc_size, alloc_size}}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_CALL: { + scc_ir_func_t *callee = + scc_ir_module_get_func(ctx->ir_module, value->data.call.callee); + int arg_count = scc_vec_size(value->data.call.args); + scc_lir_val_t *lir_args = scc_malloc(sizeof(scc_lir_val_t) * arg_count); + for (int i = 0; i < arg_count; i++) { + scc_ir_value_ref_t arg_ref = scc_vec_at(value->data.call.args, i); + lir_args[i] = ir_value_to_lir_operand(ctx, arg_ref); + } + + scc_lir_instr_t instr = { + .op = SCC_LIR_CALL, + .size = size, + .to = SCC_LIR_VREG(dst_vreg), + .metadata.call = {.callee = callee->name, + .args = lir_args, + .arg_count = arg_count, + .ret_vreg = SCC_LIR_VREG(dst_vreg), + .clobber_mask = 0}}; + scc_lir_builder_add_instr(ctx->builder, &instr); + // 注意:lir_args 内存将随指令结构体复制到基本块向量中,但 + // metadata.call.args 指针仍指向 malloc 内存, + // 这会导致内存泄漏。实际实现中应使用 arena + // 分配或随函数释放。此处为示例简化。 + break; + } + case SCC_IR_VALUE_TAG_BRANCH: { + scc_lir_val_t cond = + ir_value_to_lir_operand(ctx, value->data.branch.cond); + scc_lir_bblock_uid_t true_bb = + (scc_lir_bblock_uid_t)(uintptr_t)scc_hashtable_get( + &ctx->bb_map, + (void *)(uintptr_t)value->data.branch.true_bblock); + scc_lir_bblock_uid_t false_bb = + (scc_lir_bblock_uid_t)(uintptr_t)scc_hashtable_get( + &ctx->bb_map, + (void *)(uintptr_t)value->data.branch.false_bblock); + scc_lir_instr_t instr = { + .op = SCC_LIR_BR, .arg0 = cond, .metadata.br = {true_bb, false_bb}}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_JUMP: { + scc_lir_bblock_uid_t target = + (scc_lir_bblock_uid_t)(uintptr_t)scc_hashtable_get( + &ctx->bb_map, + (void *)(uintptr_t)value->data.jump.target_bblock); + scc_lir_instr_t instr = {.op = SCC_LIR_JMP, + .metadata.jmp_target = target}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_RET: { + scc_lir_val_t ret_val; + if (value->data.ret.ret_val != SCC_IR_REF_nullptr) { + ret_val = ir_value_to_lir_operand(ctx, value->data.ret.ret_val); + } else { + ret_val = SCC_LIR_NONE(); + } + scc_lir_instr_t instr = {.op = SCC_LIR_RET, + .metadata.ret_val = ret_val}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + case SCC_IR_VALUE_TAG_CONV: { + // 类型转换:使用 MOV 指令配合扩展/截断 + scc_lir_val_t src = + ir_value_to_lir_operand(ctx, value->data.conv.operand); + scc_lir_ext_t conv_ext = SCC_LIR_EXT_NONE; + if (value->data.conv.conv_type == CONV_SEXT) + conv_ext = SCC_LIR_EXT_SEXT; + else if (value->data.conv.conv_type == CONV_ZEXT) + conv_ext = SCC_LIR_EXT_ZEXT; + // TRUNC 用 NONE 即可(MOV 截断) + scc_lir_instr_t instr = {.op = SCC_LIR_MOV, + .size = size, + .ext = conv_ext, + .to = SCC_LIR_VREG(dst_vreg), + .arg0 = src}; + scc_lir_builder_add_instr(ctx->builder, &instr); + break; + } + // case SCC_IR_VALUE_TAG_CMP: { + // // 注意:IR 中没有单独的 CMP + // // 节点,比较通常作为二元运算的一种或分支条件的一部分。 + // // 此处假设比较操作已由前端处理为条件分支,无需生成 LIR 指令。 + // break; + // } + // 常量、参数、全局变量等已在 ir_value_to_lir_operand + // 中直接返回,不会进入此处 + default: + // 不生成指令的节点(如 CONST_INT, FUNC_ARG_REF)不会调用本函数 + break; + } +} + +/* ---------- 基本块翻译 ---------- */ + +static void translate_bblock(ir2lir_ctx_t *ctx, scc_ir_bblock_t *bblock, + scc_ir_bblock_ref_t bblock_ref) { + // 创建 LIR 基本块并记录映射 + scc_lir_builder_begin_bblock(ctx->builder, bblock->label); + scc_lir_bblock_uid_t lir_bb_id = ctx->builder->cur_bb->id; + scc_hashtable_set(&ctx->bb_map, (void *)(uintptr_t)bblock_ref, + (void *)(uintptr_t)lir_bb_id); + + // 翻译每条指令 + for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) { + scc_ir_value_ref_t val_ref = scc_vec_at(bblock->instrs, i); + scc_ir_value_t *val = scc_ir_module_get_value(ctx->ir_module, val_ref); + translate_ir_value(ctx, val, val_ref); + } + + scc_lir_builder_end_bblock(ctx->builder); +} + +/* ---------- 函数翻译 ---------- */ + +static void translate_func(ir2lir_ctx_t *ctx, scc_ir_func_t *ir_func) { + scc_lir_builder_begin_func(ctx->builder, ir_func->name); + + // 预先为所有参数分配虚拟寄存器 + for (usize i = 0; i < scc_vec_size(ir_func->params); i++) { + scc_ir_value_ref_t param_ref = scc_vec_at(ir_func->params, i); + get_vreg_for_value(ctx, param_ref); + } + + // 第一遍:创建所有基本块(空壳),建立映射 + for (usize i = 0; i < scc_vec_size(ir_func->bblocks); i++) { + scc_ir_bblock_ref_t bb_ref = scc_vec_at(ir_func->bblocks, i); + scc_ir_bblock_t *bb = scc_ir_module_get_bblock(ctx->ir_module, bb_ref); + + scc_lir_builder_begin_bblock(ctx->builder, bb->label); + scc_lir_bblock_uid_t lir_bb_id = ctx->builder->cur_bb->id; + scc_hashtable_set(&ctx->bb_map, (void *)(uintptr_t)bb_ref, + (void *)(uintptr_t)lir_bb_id); + scc_lir_builder_end_bblock(ctx->builder); + } + + // 第二遍:填充每个基本块的指令 + for (usize i = 0; i < scc_vec_size(ir_func->bblocks); i++) { + scc_ir_bblock_ref_t bb_ref = scc_vec_at(ir_func->bblocks, i); + scc_ir_bblock_t *bb = scc_ir_module_get_bblock(ctx->ir_module, bb_ref); + scc_lir_bblock_uid_t lir_bb_id = + (scc_lir_bblock_uid_t)(uintptr_t)scc_hashtable_get( + &ctx->bb_map, (void *)(uintptr_t)bb_ref); + + // 切换到该基本块 + scc_lir_bblock_t *lir_bb = nullptr; + for (usize j = 0; j < scc_vec_size(ctx->builder->func->bblocks); j++) { + if (scc_vec_at(ctx->builder->func->bblocks, j).id == lir_bb_id) { + lir_bb = &scc_vec_at(ctx->builder->func->bblocks, j); + break; + } + } + Assert(lir_bb != nullptr); + ctx->builder->cur_bb = lir_bb; + + // 翻译指令 + for (usize j = 0; j < scc_vec_size(bb->instrs); j++) { + scc_ir_value_ref_t val_ref = scc_vec_at(bb->instrs, j); + scc_ir_value_t *val = + scc_ir_module_get_value(ctx->ir_module, val_ref); + translate_ir_value(ctx, val, val_ref); + } + } + + scc_lir_builder_end_func(ctx->builder); + + // 清理本次函数翻译的临时映射 + scc_hashtable_drop(&ctx->bb_map); + scc_hashtable_drop(&ctx->value_to_vreg); +} + +/* ---------- 公开接口 ---------- */ + +scc_lir_module_t *scc_ir2lir(scc_lir_builder_t *builder, + const scc_ir_cprog_t *cprog) { + Assert(builder && builder->module && cprog); + + ir2lir_ctx_t ctx; + ir2lir_ctx_init(&ctx, builder, &cprog->module); + + // 1. 处理全局变量 + for (usize i = 0; i < scc_vec_size(cprog->global_vals); i++) { + scc_ir_value_ref_t gv_ref = scc_vec_at(cprog->global_vals, i); + scc_ir_value_t *galloc = + scc_ir_module_get_value(&cprog->module, gv_ref); + Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC); + scc_ir_value_t *val = scc_ir_module_get_value( + &cprog->module, galloc->data.global_alloc.value); + scc_ir_buffer_t *data = &val->data.const_array.fields; + const scc_lir_symbol_t *sym = scc_lir_module_add_data( + builder->module, galloc->name, SCC_LIR_SYMBOL_DATA, + scc_vec_unsafe_get_data(*data), scc_vec_size(*data), 0, 0); + Assert(sym != nullptr); + } + + // 2. 处理函数声明 (外部函数) + for (usize i = 0; i < scc_vec_size(cprog->func_decls); i++) { + scc_ir_func_ref_t func_ref = scc_vec_at(cprog->func_decls, i); + scc_ir_func_t *func = scc_ir_module_get_func(&cprog->module, func_ref); + if (!func) + continue; + const scc_lir_symbol_t *sym = + scc_lir_module_add_func_decl(builder->module, func->name, 0); + Assert(sym); + // 记录映射,供调用时使用 + scc_hashtable_set(&ctx.func_decl_map, (void *)(uintptr_t)func_ref, + (void *)func->name); + } + + // 3. 处理函数定义 + for (usize i = 0; i < scc_vec_size(cprog->func_defs); i++) { + scc_ir_func_ref_t func_ref = scc_vec_at(cprog->func_defs, i); + scc_ir_func_t *func = scc_ir_module_get_func(&cprog->module, func_ref); + if (!func) + continue; + translate_func(&ctx, func); + } + + ir2lir_ctx_drop(&ctx); + return builder->module; +} diff --git a/libs/lir/src/scc_lir_builder.c b/libs/lir/src/scc_lir_builder.c new file mode 100644 index 0000000..9d3097c --- /dev/null +++ b/libs/lir/src/scc_lir_builder.c @@ -0,0 +1,68 @@ +#include +#include + +void scc_lir_builder_init(scc_lir_builder_t *builder, + scc_lir_module_t *module) { + Assert(module != nullptr); + builder->cur_bb = nullptr; + builder->func = nullptr; + builder->module = module; + scc_hashtable_usize_init(&builder->value_to_vreg); +} + +void scc_lir_builder_drop(scc_lir_builder_t *builder) { + scc_hashtable_drop(&builder->value_to_vreg); +} + +void scc_lir_builder_begin_func(scc_lir_builder_t *builder, const char *name) { + Assert(builder != nullptr); + scc_lir_func_t *func = scc_malloc(sizeof(scc_lir_func_t)); + builder->func = func; + Assert(builder->func != nullptr); + builder->cur_bb = nullptr; + + // Init; + func->next_bb_uid = 1; + func->vregs_count = 0; + func->name = nullptr; + func->frame_size = 0; + func->attr = 0; + func->name = name; + scc_vec_init(func->bblocks); + scc_hashtable_usize_init(&func->bb_map); +} + +void scc_lir_builder_end_func(scc_lir_builder_t *builder) { + Assert(builder != nullptr && builder->module != nullptr); + scc_lir_module_add_func_def(builder->module, builder->func); + builder->func = nullptr; +} + +void scc_lir_builder_begin_bblock(scc_lir_builder_t *builder, + const char *label) { + Assert(builder != nullptr && builder->module != nullptr && + builder->func != nullptr); + Assert(builder->cur_bb == nullptr); + scc_vec_push(builder->func->bblocks, (scc_lir_bblock_t){0}); + builder->cur_bb = &scc_vec_at(builder->func->bblocks, + scc_vec_size(builder->func->bblocks) - 1); + + builder->cur_bb->id = builder->func->next_bb_uid++; + scc_vec_init(builder->cur_bb->ins); + builder->cur_bb->label = label; +} + +void scc_lir_builder_end_bblock(scc_lir_builder_t *builder) { + builder->cur_bb = nullptr; +} + +void scc_lir_builder_add_instr(scc_lir_builder_t *builder, + const scc_lir_instr_t *instr) { + Assert(builder != nullptr && builder->cur_bb != nullptr && + instr != nullptr); + scc_vec_push(builder->cur_bb->ins, *instr); +} + +unsigned int scc_lir_builder_new_vreg(scc_lir_builder_t *builder) { + return builder->func->vregs_count++; +} diff --git a/libs/lir/src/scc_lir_dump.c b/libs/lir/src/scc_lir_dump.c new file mode 100644 index 0000000..a8a29b9 --- /dev/null +++ b/libs/lir/src/scc_lir_dump.c @@ -0,0 +1,452 @@ +/** + * @file scc_lir_dump.c + * @brief LIR 文本 dump 实现 + */ + +#include "scc_lir_dump.h" +#include + +static const char *op_to_string(scc_lir_op_t op) { + switch (op) { + case SCC_LIR_MOV: + return "mov"; + case SCC_LIR_LOAD: + return "load"; + case SCC_LIR_LOAD_ADDR: + return "load.addr"; + case SCC_LIR_STORE: + return "store"; + case SCC_LIR_STORE_ADDR: + return "store.addr"; + case SCC_LIR_LEA: + return "lea"; + case SCC_LIR_ADD: + return "add"; + case SCC_LIR_SUB: + return "sub"; + case SCC_LIR_MUL: + return "mul"; + case SCC_LIR_DIV_S: + return "div.s"; + case SCC_LIR_DIV_U: + return "div.u"; + case SCC_LIR_REM_S: + return "rem.s"; + case SCC_LIR_REM_U: + return "rem.u"; + case SCC_LIR_AND: + return "and"; + case SCC_LIR_OR: + return "or"; + case SCC_LIR_XOR: + return "xor"; + case SCC_LIR_SHL: + return "shl"; + case SCC_LIR_SHR: + return "shr"; + case SCC_LIR_SAR: + return "sar"; + case SCC_LIR_NEG: + return "neg"; + case SCC_LIR_NOT: + return "not"; + case SCC_LIR_FADD: + return "fadd"; + case SCC_LIR_FSUB: + return "fsub"; + case SCC_LIR_FMUL: + return "fmul"; + case SCC_LIR_FDIV: + return "fdiv"; + case SCC_LIR_FNEG: + return "fneg"; + case SCC_LIR_FCVT: + return "fcvt"; + case SCC_LIR_CMP: + return "cmp"; + case SCC_LIR_BR: + return "br"; + case SCC_LIR_JMP: + return "jmp"; + case SCC_LIR_JMP_INDIRECT: + return "jmp.indirect"; + case SCC_LIR_CALL: + return "call"; + case SCC_LIR_CALL_INDIRECT: + return "call.indirect"; + case SCC_LIR_RET: + return "ret"; + case SCC_LIR_PARALLEL_COPY: + return "parallel_copy"; + case SCC_LIR_VA_START: + return "va_start"; + case SCC_LIR_VA_ARG: + return "va_arg"; + case SCC_LIR_VA_END: + return "va_end"; + case SCC_LIR_VA_COPY: + return "va_copy"; + case SCC_LIR_ALLOCA: + return "alloca"; + case SCC_LIR_NOP: + return "nop"; + default: + return "???"; + } +} + +static const char *cond_to_string(scc_lir_cond_t cond) { + switch (cond) { + case SCC_LIR_COND_EQ: + return "eq"; + case SCC_LIR_COND_NE: + return "ne"; + case SCC_LIR_COND_SLT: + return "slt"; + case SCC_LIR_COND_SLE: + return "sle"; + case SCC_LIR_COND_SGT: + return "sgt"; + case SCC_LIR_COND_SGE: + return "sge"; + case SCC_LIR_COND_ULT: + return "ult"; + case SCC_LIR_COND_ULE: + return "ule"; + case SCC_LIR_COND_UGT: + return "ugt"; + case SCC_LIR_COND_UGE: + return "uge"; + case SCC_LIR_COND_FEQ: + return "feq"; + case SCC_LIR_COND_FNE: + return "fne"; + case SCC_LIR_COND_FLT: + return "flt"; + case SCC_LIR_COND_FLE: + return "fle"; + case SCC_LIR_COND_FGT: + return "fgt"; + case SCC_LIR_COND_FGE: + return "fge"; + default: + return "???"; + } +} + +static void dump_operand(scc_lir_dump_ctx_t *ctx, const scc_lir_val_t *op) { + scc_tree_dump_t *td = ctx->dump_ctx; + + switch (op->kind) { + case SCC_LIR_INSTR_KIND_NONE: + scc_tree_dump_append(td, "_"); + break; + case SCC_LIR_INSTR_KIND_VREG: + scc_tree_dump_append_fmt(td, "%%%u", op->data.reg); + break; + case SCC_LIR_INSTR_KIND_PREG: + scc_tree_dump_append_fmt(td, "Phy%u", op->data.reg); + break; + case SCC_LIR_INSTR_KIND_IMM: + scc_tree_dump_append_fmt(td, "%lld", op->data.imm); + break; + case SCC_LIR_INSTR_KIND_FIMM: + scc_tree_dump_append_fmt(td, "%lf", op->data.fimm); + break; + case SCC_LIR_INSTR_KIND_SYMBOL: + scc_tree_dump_append_fmt(td, "@%s", + op->data.symbol ? op->data.symbol : ""); + break; + case SCC_LIR_INSTR_KIND_ADDR: { + const scc_lir_addr_t *addr = &op->data.addr; + scc_tree_dump_append(td, "["); + if (addr->base != -1) { + scc_tree_dump_append_fmt(td, "%%%d", addr->base); + } + if (addr->index != -1) { + scc_tree_dump_append_fmt(td, " + %%%d * %d", addr->index, + addr->scale); + } + if (addr->offset != 0) { + if (addr->offset > 0) + scc_tree_dump_append_fmt(td, " + %lld", + (long long)addr->offset); + else + scc_tree_dump_append_fmt(td, " - %lld", + -(long long)addr->offset); + } + if (addr->base == -1 && addr->index == -1 && addr->offset == 0) + scc_tree_dump_append(td, "0"); + scc_tree_dump_append(td, "]"); + break; + } + default: + scc_tree_dump_append(td, ""); + } +} + +static void dump_size_ext(scc_lir_dump_ctx_t *ctx, u8 size, scc_lir_ext_t ext) { + scc_tree_dump_t *td = ctx->dump_ctx; + const char *size_str = ""; + if (size == SCC_LIR_SIZE_8) + size_str = "8"; + else if (size == SCC_LIR_SIZE_16) + size_str = "16"; + else if (size == SCC_LIR_SIZE_32) + size_str = "32"; + else if (size == SCC_LIR_SIZE_64) + size_str = "64"; + + const char *ext_str = ""; + if (ext == SCC_LIR_EXT_SEXT) + ext_str = ".s"; + else if (ext == SCC_LIR_EXT_ZEXT) + ext_str = ".u"; + else if (ext == SCC_LIR_EXT_FLOAT) + ext_str = ".f"; + + if (size_str[0] || ext_str[0]) { + scc_tree_dump_append_fmt(td, ".%s%s", size_str, ext_str); + } +} + +void scc_lir_dump_ins(scc_lir_dump_ctx_t *ctx, const scc_lir_instr_t *ins) { + Assert(ctx != nullptr && ins != nullptr); + scc_tree_dump_t *td = ctx->dump_ctx; + + scc_tree_dump_begin_line(td); + scc_tree_dump_append(td, " "); + // 输出操作码(带节点颜色) + scc_tree_dump_node(td, "%s", op_to_string(ins->op)); + + // 输出宽度和扩展标志 + dump_size_ext(ctx, ins->size, ins->ext); + scc_tree_dump_append(td, " "); + + switch (ins->op) { + case SCC_LIR_MOV: + case SCC_LIR_LOAD: + case SCC_LIR_LOAD_ADDR: + dump_operand(ctx, &ins->to); + scc_tree_dump_append(td, " <- "); + dump_operand(ctx, &ins->arg0); + break; + case SCC_LIR_LEA: + case SCC_LIR_NEG: + case SCC_LIR_NOT: + case SCC_LIR_FNEG: + case SCC_LIR_FCVT: + case SCC_LIR_ALLOCA: + dump_operand(ctx, &ins->to); + if (ins->op != SCC_LIR_ALLOCA) { + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->arg0); + // alloca 额外信息在 metadata 中,但通常只关注 to + } + break; + + case SCC_LIR_STORE: + case SCC_LIR_STORE_ADDR: + dump_operand(ctx, &ins->arg0); + scc_tree_dump_append(td, " -> "); + dump_operand(ctx, &ins->arg1); + break; + + case SCC_LIR_ADD: + case SCC_LIR_SUB: + case SCC_LIR_MUL: + case SCC_LIR_DIV_S: + case SCC_LIR_DIV_U: + case SCC_LIR_REM_S: + case SCC_LIR_REM_U: + case SCC_LIR_AND: + case SCC_LIR_OR: + case SCC_LIR_XOR: + case SCC_LIR_SHL: + case SCC_LIR_SHR: + case SCC_LIR_SAR: + case SCC_LIR_FADD: + case SCC_LIR_FSUB: + case SCC_LIR_FMUL: + case SCC_LIR_FDIV: + dump_operand(ctx, &ins->to); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->arg0); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->arg1); + break; + + case SCC_LIR_CMP: + dump_operand(ctx, &ins->to); + scc_tree_dump_append_fmt(td, ", %s, ", + cond_to_string(ins->metadata.cond)); + dump_operand(ctx, &ins->arg0); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->arg1); + break; + + case SCC_LIR_BR: + dump_operand(ctx, &ins->arg0); + scc_tree_dump_append_fmt(td, ", BB#%zu, BB#%zu", + ins->metadata.br.true_target, + ins->metadata.br.false_target); + break; + + case SCC_LIR_JMP: + scc_tree_dump_append_fmt(td, "BB#%zu", ins->metadata.jmp_target); + break; + + case SCC_LIR_JMP_INDIRECT: + dump_operand(ctx, &ins->arg0); + break; + + case SCC_LIR_CALL: { + const struct scc_lir_call *c = &ins->metadata.call; + if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { + dump_operand(ctx, &c->ret_vreg); + scc_tree_dump_append(td, " = "); + } + scc_tree_dump_append_fmt(td, "call @%s(", + c->callee ? c->callee : ""); + for (u8 i = 0; i < c->arg_count; i++) { + if (i > 0) + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &c->args[i]); + } + scc_tree_dump_append_fmt(td, ") clobber=0x%llx", + (unsigned long long)c->clobber_mask); + break; + } + + case SCC_LIR_CALL_INDIRECT: { + const struct scc_lir_call_indirect *c = &ins->metadata.call_indirect; + if (c->ret_vreg.kind != SCC_LIR_INSTR_KIND_NONE) { + dump_operand(ctx, &c->ret_vreg); + scc_tree_dump_append(td, " = "); + } + scc_tree_dump_append(td, "call "); + dump_operand(ctx, &c->target); + scc_tree_dump_append(td, "("); + for (u8 i = 0; i < c->arg_count; i++) { + if (i > 0) + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &c->args[i]); + } + scc_tree_dump_append_fmt(td, ") clobber=0x%llx", + (unsigned long long)c->clobber_mask); + break; + } + + case SCC_LIR_RET: + if (ins->metadata.ret_val.kind != SCC_LIR_INSTR_KIND_NONE) { + dump_operand(ctx, &ins->metadata.ret_val); + } + break; + + case SCC_LIR_PARALLEL_COPY: { + const struct scc_lir_parallel_copy *pc = &ins->metadata.parallel_copy; + scc_tree_dump_append(td, "["); + for (u8 i = 0; i < pc->num_copies; i++) { + if (i > 0) + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &pc->dests[i]); + scc_tree_dump_append(td, " <- "); + dump_operand(ctx, &pc->srcs[i]); + } + scc_tree_dump_append(td, "]"); + break; + } + + case SCC_LIR_VA_START: + dump_operand(ctx, &ins->metadata.va_start.ap); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.va_start.last); + break; + + case SCC_LIR_VA_ARG: + dump_operand(ctx, &ins->metadata.va_arg.to); + scc_tree_dump_append(td, " = va_arg "); + dump_operand(ctx, &ins->metadata.va_arg.ap); + scc_tree_dump_append_fmt( + td, ", size=%u, align=%u, float=%d", ins->metadata.va_arg.type_size, + ins->metadata.va_arg.type_align, ins->metadata.va_arg.is_float); + break; + + case SCC_LIR_VA_END: + dump_operand(ctx, &ins->metadata.va_end.ap); + break; + + case SCC_LIR_VA_COPY: + dump_operand(ctx, &ins->metadata.va_copy.dest); + scc_tree_dump_append(td, ", "); + dump_operand(ctx, &ins->metadata.va_copy.src); + break; + + case SCC_LIR_NOP: + break; + } +} + +void scc_lir_dump_bblock(scc_lir_dump_ctx_t *ctx, const scc_lir_bblock_t *bb) { + Assert(ctx != nullptr && bb != nullptr); + scc_tree_dump_t *td = ctx->dump_ctx; + + // 基本块头部 + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "BB%zu", bb->id); + if (bb->label) { + scc_tree_dump_append_fmt(td, " (%s)", bb->label); + } + scc_tree_dump_append(td, ":"); + + // 输出每条指令 + for (usize i = 0; i < scc_vec_size(bb->ins); ++i) { + const scc_lir_instr_t *ins = &scc_vec_at(bb->ins, i); + scc_lir_dump_ins(ctx, ins); + } +} + +void scc_lir_dump_func(scc_lir_dump_ctx_t *ctx, const scc_lir_func_t *func) { + Assert(ctx != nullptr && func != nullptr); + scc_tree_dump_t *td = ctx->dump_ctx; + + // 函数头部 + scc_tree_dump_begin_line(td); + scc_tree_dump_node(td, "func @%s", func->name ? func->name : ""); + scc_tree_dump_append_fmt(td, " (vregs: %u, frame: %d)", func->vregs_count, + func->frame_size); + if (func->attr != SCC_LIR_ATTR_NONE) { + scc_tree_dump_append(td, " [attr:"); + if (func->attr & SCC_LIR_ATTR_STATIC) + scc_tree_dump_append(td, " static"); + if (func->attr & SCC_LIR_ATTR_WEAK) + scc_tree_dump_append(td, " weak"); + scc_tree_dump_append(td, " ]"); + } + scc_tree_dump_append(td, " {"); + + // 输出所有基本块 + for (usize i = 0; i < scc_vec_size(func->bblocks); ++i) { + const scc_lir_bblock_t *bb = &scc_vec_at(func->bblocks, i); + scc_lir_dump_bblock(ctx, bb); + } + + scc_tree_dump_begin_line(td); + scc_tree_dump_append(td, "}"); +} + +void scc_lir_dump_module(scc_lir_dump_ctx_t *ctx, + const scc_lir_module_t *module) { + scc_vec_foreach(module->symbols, i) { + // FIXME 0 is null + if (i == 0) + continue; + scc_lir_symbol_t *sym = &scc_vec_at(module->symbols, i); + scc_tree_dump_begin_line(ctx->dump_ctx); + scc_tree_dump_node(ctx->dump_ctx, "symbol"); + scc_tree_dump_append_fmt(ctx->dump_ctx, " %s", sym->name); + } + scc_vec_foreach(module->funcs, i) { + scc_lir_dump_func(ctx, scc_vec_at(module->funcs, i)); + } +} diff --git a/libs/lir/src/scc_lir_module.c b/libs/lir/src/scc_lir_module.c new file mode 100644 index 0000000..0ccfc0b --- /dev/null +++ b/libs/lir/src/scc_lir_module.c @@ -0,0 +1,172 @@ +#include + +static void scc_lir_func_drop(scc_lir_func_t *func) { + if (!func) + return; + + /* 释放每个基本块内的指令向量 */ + for (usize i = 0; i < scc_vec_size(func->bblocks); ++i) { + scc_lir_bblock_t *bb = &func->bblocks.data[i]; + scc_vec_free(bb->ins); + } + scc_vec_free(func->bblocks); + scc_hashtable_drop(&func->bb_map); + scc_free(func); +} + +static scc_lir_symbol_t *lookup_symbol(const scc_lir_module_t *module, + const char *name) { + if (!module || !name) + return nullptr; + /* 注意:scc_hashtable_get 返回的是 (void*) 存储的 usize 索引 */ + void *idx_val = + scc_hashtable_get((scc_hashtable_t *)&module->symbol_map, (void *)name); + if (!idx_val) + return nullptr; + usize idx = (usize)idx_val; + if (idx >= scc_vec_size(module->symbols)) + return nullptr; + return &module->symbols.data[idx]; +} + +void scc_lir_module_init(scc_lir_module_t *module) { + scc_vec_init(module->funcs); + scc_vec_init(module->symbols); + scc_hashtable_cstr_init(&module->symbol_map); + + // /* 预留索引 0 作为无效 func_id */ + // scc_vec_push(module->funcs, nullptr); + scc_vec_push(module->symbols, (scc_lir_symbol_t){0}); +} + +void scc_lir_module_drop(scc_lir_module_t *module) { + /* 释放所有函数对象 */ + for (usize i = 0; i < scc_vec_size(module->funcs); ++i) { + scc_lir_func_drop(module->funcs.data[i]); + } + scc_vec_free(module->funcs); + + /* 释放数据符号中动态分配的初始化数据 */ + for (usize i = 0; i < scc_vec_size(module->symbols); ++i) { + scc_lir_symbol_t *sym = &module->symbols.data[i]; + if ((sym->kind == SCC_LIR_SYMBOL_DATA) && sym->data.init_data) { + scc_free(sym->data.init_data); + } + } + scc_vec_free(module->symbols); + + scc_hashtable_drop(&module->symbol_map); +} + +static const scc_lir_symbol_t *register_symbol(scc_lir_module_t *module, + scc_lir_symbol_t *sym) { + /* 检查是否已存在同名符号 */ + void *existing = scc_hashtable_get(&module->symbol_map, (void *)sym->name); + if (existing) { + LOG_ERROR("symbol '%s' already defined", sym->name); + return nullptr; + } + + usize idx = scc_vec_size(module->symbols); + scc_vec_push(module->symbols, *sym); + scc_hashtable_set(&module->symbol_map, (void *)sym->name, (void *)idx); + return &scc_vec_at(module->symbols, idx); +} + +const scc_lir_symbol_t *scc_lir_module_add_func_def(scc_lir_module_t *module, + scc_lir_func_t *func) { + if (!module || !func || !func->name) + return nullptr; + + scc_vec_push(module->funcs, func); + + scc_lir_symbol_t *func_decl_sym = lookup_symbol(module, (void *)func->name); + if (func_decl_sym) { + if (func_decl_sym->kind != SCC_LIR_SYMBOL_FUNC || + func_decl_sym->func.func != nullptr) { + Panic("Symbol already exists"); + } + func_decl_sym->func.func = func; + return func_decl_sym; + } + + /* 构建符号 */ + scc_lir_symbol_t sym = {.name = func->name, + .kind = SCC_LIR_SYMBOL_FUNC, + .attr = func->attr, + .func.func = func}; + + const scc_lir_symbol_t *result = register_symbol(module, &sym); + if (!result) { + /* 符号冲突:回滚函数添加并释放 func */ + module->funcs.size--; + scc_lir_func_drop(func); + return nullptr; + } + return result; +} + +const scc_lir_symbol_t *scc_lir_module_add_func_decl(scc_lir_module_t *module, + const char *name, + scc_lir_attr_t attr) { + if (!module || !name) + return nullptr; + + scc_lir_symbol_t sym = {.name = name, + .kind = SCC_LIR_SYMBOL_FUNC, + .attr = attr, + .func.func = nullptr}; + + return register_symbol(module, &sym); +} + +const scc_lir_symbol_t * +scc_lir_module_add_data(scc_lir_module_t *module, const char *name, + scc_lir_symbol_kind_t kind, const u8 *init_data, + usize size, u32 align, scc_lir_attr_t attr) { + if (!module || !name) + return nullptr; + if (kind != SCC_LIR_SYMBOL_DATA && kind != SCC_LIR_SYMBOL_EXTERN) + return nullptr; + + scc_lir_symbol_t sym = { + .name = name, + .kind = kind, + .attr = attr, + .data = {.init_data = nullptr, .size = size, .align = align}}; + + /* 对于数据定义,复制初始化数据(若有) */ + if (kind == SCC_LIR_SYMBOL_DATA && init_data && size > 0) { + sym.data.init_data = scc_malloc(size); + if (!sym.data.init_data) { + LOG_FATAL("out of memory for data symbol '%s'", name); + } + scc_memcpy(sym.data.init_data, init_data, size); + } else if (kind == SCC_LIR_SYMBOL_DATA && !init_data) { + /* 零初始化:分配并清零 */ + sym.data.init_data = scc_calloc(1, size); + if (!sym.data.init_data) { + LOG_FATAL("out of memory for data symbol '%s'", name); + } + } + + const scc_lir_symbol_t *result = register_symbol(module, &sym); + if (!result) { + /* 冲突时释放已分配的数据 */ + scc_free(sym.data.init_data); + return nullptr; + } + return result; +} + +const scc_lir_symbol_t * +scc_lir_module_lookup_symbol(const scc_lir_module_t *module, const char *name) { + return lookup_symbol(module, name); +} + +scc_lir_func_t *scc_lir_module_get_func(const scc_lir_module_t *module, + unsigned func_id) { + if (!module || func_id == 0 || func_id >= scc_vec_size(module->funcs)) + return nullptr; + return module->funcs.data[func_id]; +} \ No newline at end of file diff --git a/runtime/scc_utils/include/scc_hashtable.h b/runtime/scc_utils/include/scc_hashtable.h index 0bc7cb5..f7f3419 100644 --- a/runtime/scc_utils/include/scc_hashtable.h +++ b/runtime/scc_utils/include/scc_hashtable.h @@ -74,6 +74,7 @@ void scc_hashtable_init(scc_hashtable_t *ht, scc_hashtable_equal_func_t cmp_func, void *userdata); void scc_hashtable_cstr_init(scc_hashtable_t *ht); +void scc_hashtable_usize_init(scc_hashtable_t *ht); /** * @brief 插入/更新键值对 diff --git a/runtime/scc_utils/src/hashtable.c b/runtime/scc_utils/src/hashtable.c index cad7fcc..62cf797 100644 --- a/runtime/scc_utils/src/hashtable.c +++ b/runtime/scc_utils/src/hashtable.c @@ -31,6 +31,19 @@ void scc_hashtable_cstr_init(scc_hashtable_t *ht) { scc_hashtable_init(ht, ht_strhash, ht_strcmp, nullptr); } +static u32 ht_usizehash(const void *key, void *userdata) { + (void)userdata; + return (u32)(usize)key; +} + +static int ht_usizecmp(const void *key1, const void *key2, void *userdata) { + (void)userdata; + return (usize)key1 - (usize)key2; +} +void scc_hashtable_usize_init(scc_hashtable_t *ht) { + scc_hashtable_init(ht, ht_usizehash, ht_usizecmp, nullptr); +} + static int next_power_of_two(int n) { n--; n |= n >> 1; diff --git a/src/config.h b/src/config.h index 1f13424..cf2e5f5 100644 --- a/src/config.h +++ b/src/config.h @@ -15,6 +15,7 @@ typedef struct { cbool emit_pp; cbool emit_ast; cbool emit_ir; + cbool emit_lir; } scc_config_t; static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, @@ -35,6 +36,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, SCC_HINT_EMIT_PP, SCC_HINT_EMIT_AST, SCC_HINT_EMIT_IR, + SCC_HINT_EMIT_LIR, }; static const char *scc_hints_en[] = { [SCC_HINT_PROG_NAME] = "scc", @@ -54,6 +56,8 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit", [SCC_HINT_EMIT_AST] = "Generate AST and exit", [SCC_HINT_EMIT_IR] = "Generate IR and exit", + [SCC_HINT_EMIT_LIR] = "Generate LIR and exit", + }; static const char *scc_hints_zh[] = { [SCC_HINT_PROG_NAME] = "scc", @@ -71,6 +75,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, [SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出", [SCC_HINT_EMIT_AST] = "生成`抽象语法树`并退出", [SCC_HINT_EMIT_IR] = "生成`中间代码`并退出", + [SCC_HINT_EMIT_LIR] = "生成`低级中间代码`并退出", }; const char **scc_hints; @@ -167,6 +172,13 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, scc_argparse_opt_init(&opt_ir, 'R', "emit-ir", scc_hints[SCC_HINT_EMIT_IR]); scc_argparse_spec_setup_bool(&opt_ir.spec, &(config->emit_ir)); scc_argparse_cmd_add_opt(root, &opt_ir); + + // -L, --emit-lir + scc_argparse_opt_t opt_lir; + scc_argparse_opt_init(&opt_lir, 'L', "emit-lir", + scc_hints[SCC_HINT_EMIT_LIR]); + scc_argparse_spec_setup_bool(&opt_lir.spec, &(config->emit_lir)); + scc_argparse_cmd_add_opt(root, &opt_lir); } #endif /* __SCC_CONFIG_H___ */ diff --git a/src/main.c b/src/main.c index a19912c..7cfdb85 100644 --- a/src/main.c +++ b/src/main.c @@ -6,8 +6,11 @@ #include #include #include -#include -#include + +#include +#include +// #include +// #include #include "config.h" @@ -238,24 +241,47 @@ sstream_drop: return 0; } - 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); + scc_lir_builder_t lir_builder; + scc_lir_module_t lir_module; + scc_lir_module_init(&lir_module); + scc_lir_builder_init(&lir_builder, &lir_module); + scc_ir2lir(&lir_builder, &cprog); + if (config.emit_lir) { + scc_lir_dump_ctx_t lir_dump_ctx; + scc_tree_dump_t tree_dump; + if (fp == nullptr) { + scc_tree_dump_init(&tree_dump, true); + } else { + scc_tree_dump_init(&tree_dump, false); + } + scc_lir_dump_init(&lir_dump_ctx, &tree_dump); + // scc_ir_dump_cprog(&ir_dump_ctx); + scc_lir_dump_module(&lir_dump_ctx, &lir_module); - sccf_builder_set_entry_symbol_name(&sccf_builder, - config.entry_point_symbol); - const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder); - scc_pe_builder_t pe_builder; - sccf2pe(&pe_builder, sccf); - - if (fp == nullptr) { - scc_printf("output exe at %s\n", config.output_file); - } else { - scc_pe_dump_to_file(&pe_builder, config.output_file); + scc_tree_dump_flush(&tree_dump, tree_dump_output, + fp == nullptr ? scc_stdout : fp); + scc_tree_dump_drop(&tree_dump); + return 0; } + // 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); + + // sccf_builder_set_entry_symbol_name(&sccf_builder, + // config.entry_point_symbol); + // const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder); + // scc_pe_builder_t pe_builder; + // sccf2pe(&pe_builder, sccf); + + // if (fp == nullptr) { + // scc_printf("output exe at %s\n", config.output_file); + // } else { + // scc_pe_dump_to_file(&pe_builder, config.output_file); + // } + return 0; }