- 将scc_ast_ctx重命名为scc_ast_module以更好地反映其功能 - 添加scc_strpool_t用于统一管理AST节点名称字符串的生命周期 - 实现scc_ast_module_intern函数用于字符串驻留 - 更新所有相关的初始化、销毁和访问函数命名 - 修改内存分配宏以使用新的模块结构 refactor(parser): 更新解析器以使用AST模块和字符串池 - 将解析器中的ast_ctx字段替换为ast_module - 在创建AST节点时使用新的ast_module参数 - 使用scc_ast_module_intern函数处理标识符和字符串字面量 - 确保所有字符串都被正确驻留到模块的字符串池中 refactor(sema): 更新语义分析器使用AST模块 - 将sema_ctx中的ast_ctx字段替换为ast_module - 更新语义分析器初始化函数参数 refactor(ast2ir): 更新AST到IR转换器使用AST模块 - 将ast_ctx字段替换为ast_module - 更新上下文初始化函数参数和实现 fix(cfg): 修复CFG模块中的符号查找错误 - 修正scc_cfg_module_unsafe_get_symbol函数中的边界检查条件 perf(ir): 完善各IR层模块的内存清理机制 - 为HIR模块添加函数和基本块元数据的释放逻辑 - 为MIR和LIR模块完善完整的资源清理和内存释放 - 确保所有分配的元数据结构都能被正确释放 chore(deps): 添加scc_utils依赖到AST库 - 在libs/ast/cbuild.toml中添加对scc_utils的依赖
91 lines
2.8 KiB
C
91 lines
2.8 KiB
C
#ifndef __SCC_MIR_H__
|
||
#define __SCC_MIR_H__
|
||
|
||
#include <scc_cfg.h>
|
||
|
||
// 伪指令 opcode(负数),所有后端通用约定
|
||
typedef enum {
|
||
SCC_MIR_PSEUDO_NONE = 0,
|
||
SCC_MIR_PSEUDO_ALLOCA = -1,
|
||
SCC_MIR_PSEUDO_VA_START = -2,
|
||
} scc_mir_pseudo_t;
|
||
|
||
typedef struct scc_mir_instr {
|
||
int opcode;
|
||
union {
|
||
struct {
|
||
int size;
|
||
int align;
|
||
int vreg;
|
||
} alloc;
|
||
} data;
|
||
} scc_mir_instr_t;
|
||
|
||
#define SCC_MIR_BBLOCK_VALUES_PTR(bb) ((void *)(&(bb)->values))
|
||
|
||
// 栈槽信息(由 FrameLayout Pass 填充)
|
||
typedef struct scc_mir_stack_slot {
|
||
int slot_id;
|
||
int size; // 通常是 8 字节 (指针大小)
|
||
int alignment; // 对齐要求
|
||
int offset; // 相对于 RSP 的偏移 (最终确定)
|
||
int arg_idx; // == 0 means local slot, > 0 means argument slot
|
||
} scc_mir_stack_slot_t;
|
||
typedef SCC_VEC(scc_mir_stack_slot_t) scc_mir_stack_slot_vec_t;
|
||
|
||
typedef scc_cfg_bblock_t scc_mir_bblock_t;
|
||
|
||
// 函数元数据 —— 不包含任何指令结构,由各后端自行定义指令布局
|
||
typedef scc_cfg_func_t scc_mir_func_t;
|
||
typedef struct scc_mir_func_meta {
|
||
int need_va_args;
|
||
int frame_size;
|
||
int stack_alignment;
|
||
int vregs_count;
|
||
|
||
void *target_data; // 目标后端私有数据,例如 x86_64_func_info_t*
|
||
|
||
scc_mir_stack_slot_vec_t stack_slots;
|
||
// vreg -> phys reg / stack slot
|
||
// 0 = not mapped (still a vreg)
|
||
// >0 = stack slot index
|
||
// <0 = physical register (negated)
|
||
scc_hashtable_t vreg2physic;
|
||
} scc_mir_func_meta_t;
|
||
#define SCC_MIR_FUNC_META(func) ((scc_mir_func_meta_t *)(func)->meta)
|
||
|
||
void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta);
|
||
|
||
int scc_mir_alloc_vreg(scc_mir_func_t *func);
|
||
void scc_mir_vreg_map2preg(scc_mir_func_t *func, int vreg, int preg);
|
||
int scc_mir_vreg_map2slot(scc_mir_func_t *func, int vreg, int size, int align);
|
||
|
||
// 从 vreg2physic 表中查询映射结果:
|
||
// 返回 0 → 该 vreg 仍为 vreg,未映射
|
||
// 返回 1 → 已映射到物理寄存器,*out_preg 有效
|
||
// 返回 -1 → 已溢出到栈槽,*out_slot 有效
|
||
static inline int scc_mir_vreg_lookup(const scc_mir_func_t *func, int vreg,
|
||
int *out) {
|
||
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
|
||
isize idx =
|
||
(isize)scc_hashtable_get(&meta->vreg2physic, (void *)(usize)vreg);
|
||
if (idx == 0)
|
||
return 0;
|
||
if (idx < 0) {
|
||
*out = (int)-idx;
|
||
return 1;
|
||
}
|
||
*out = (int)idx;
|
||
return -1;
|
||
}
|
||
|
||
static inline scc_mir_stack_slot_t *
|
||
scc_mir_unsafe_slot(const scc_mir_func_t *func, int slot) {
|
||
Assert(slot > 0);
|
||
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
|
||
Assert((usize)slot < scc_vec_size(meta->stack_slots));
|
||
return &scc_vec_at(meta->stack_slots, slot);
|
||
}
|
||
|
||
#endif /* __SCC_MIR_H__ */
|