diff --git a/libs/ast2ir/src/scc_ast2ir.c b/libs/ast2ir/src/scc_ast2ir.c index 0464931..c676c39 100644 --- a/libs/ast2ir/src/scc_ast2ir.c +++ b/libs/ast2ir/src/scc_ast2ir.c @@ -470,11 +470,12 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr, } case SCC_AST_EXPR_STRING_LITERAL: { // FIXME - scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme, - scc_strlen(expr->literal.lexme)); + scc_ir_value_ref_t value = + scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme, + scc_strlen(expr->literal.lexme)); if (is_lvalue) TODO(); - break; + return value; } case SCC_AST_EXPR_IDENTIFIER: { if (expr->identifier._target == nullptr) { @@ -718,28 +719,35 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) { } scc_ir_value_ref_t init_val_node = scc_ast2ir_expr(ctx, decl->var.init, false); + Assert(init_val_node != nullptr); // FIXME array auto calucate size scc_ir_type_t *ir_type = scc_ir_module_get_type(ctx->builder.ctx.module, ir_type_ref); - if (ir_type->tag == SCC_IR_TYPE_ARRAY && ir_type->data.array.len == 0) { - scc_ast_expr_t *init_expr = decl->var.init; - if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) { - Panic("TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND"); - } else if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) { - ir_type->data.array.len = - scc_strlen(init_expr->literal.lexme) + 1; + if (ir_type->tag == SCC_IR_TYPE_ARRAY) { + if (ir_type->data.array.len == 0) { + scc_ast_expr_t *init_expr = decl->var.init; + if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) { + Panic( + "TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND"); + } else if (init_expr->base.type == + SCC_AST_EXPR_STRING_LITERAL) { + ir_type->data.array.len = + scc_strlen(init_expr->literal.lexme) + 1; - scc_ir_const_int_t len = {.int64 = ir_type->data.array.len}; - scc_ir_value_ref_t len_ref = scc_ir_builder_const_int( - &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), len); - scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node, - init_val_node, len_ref); - } else { - Panic("unknown init expr in array decl"); + scc_ir_const_int_t len = {.int64 = ir_type->data.array.len}; + scc_ir_value_ref_t len_ref = scc_ir_builder_const_int( + &ctx->builder, scc_ir_builder_type_u64(&ctx->builder), + len); + scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node, + init_val_node, len_ref); + } else { + Panic("unknown init expr in array decl"); + } } + } else { + scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node); } - scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node); break; } case SCC_AST_DECL_FUNC: { diff --git a/libs/ir/include/ir_builder.h b/libs/ir/include/ir_builder.h index 61acead..b6cddf6 100644 --- a/libs/ir/include/ir_builder.h +++ b/libs/ir/include/ir_builder.h @@ -72,6 +72,7 @@ static inline scc_ir_value_ref_t scc_ir_builder_builtin_memcpy(scc_ir_builder_t *builder, scc_ir_value_ref_t dest, scc_ir_value_ref_t src, scc_ir_value_ref_t len) { + Assert(builder && src && dest && len); scc_ir_value_t value; scc_ir_value_init(&value, nullptr, SCC_IR_VALUE_TAG_BUILTIN); value.type = scc_ir_builder_type_void(builder); // memcpy 返回 void* diff --git a/libs/ir/src/ir_ctx.c b/libs/ir/src/ir_ctx.c index 4182d2d..7a5f77d 100644 --- a/libs/ir/src/ir_ctx.c +++ b/libs/ir/src/ir_ctx.c @@ -64,6 +64,10 @@ static u32 hash_type(const void *_key) { } static int cmp_type(const void *_key1, const void *_key2) { const scc_ir_type_t *key1 = _key1, *key2 = _key2; + Assert(key1 != nullptr && key2 != nullptr); + if (key1->tag == SCC_IR_TYPE_unknown || key2->tag == SCC_IR_TYPE_unknown) { + return 1; + } // tag不同 if (key1->tag != key2->tag) { return 1; diff --git a/libs/ir/src/ir_dump.c b/libs/ir/src/ir_dump.c index 2cf9e50..dd2b6e6 100644 --- a/libs/ir/src/ir_dump.c +++ b/libs/ir/src/ir_dump.c @@ -481,9 +481,17 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx, switch (value->tag) { case SCC_IR_VALUE_TAG_BUILTIN: { + scc_tree_dump_append(ctx->dump_ctx, "@scc::"); switch (value->data.builtin.tag) { case SCC_IR_BUILTIN_TAG_MEMCPY: scc_tree_dump_append(ctx->dump_ctx, "memcpy"); + scc_tree_dump_append(ctx->dump_ctx, "("); + format_ref_or_value(ctx, value->data.builtin.func.memcpy.dest); + scc_tree_dump_append(ctx->dump_ctx, ", "); + format_ref_or_value(ctx, value->data.builtin.func.memcpy.src); + scc_tree_dump_append(ctx->dump_ctx, ", "); + format_ref_or_value(ctx, value->data.builtin.func.memcpy.size); + scc_tree_dump_append(ctx->dump_ctx, ")"); break; case SCC_IR_BUILTIN_TAG_MEMSET: scc_tree_dump_append(ctx->dump_ctx, "memset"); @@ -606,7 +614,8 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx, value->data.arg_ref.idx); break; case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: - scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s\n", value->name); + scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s", value->name); + scc_tree_dump_begin_line(ctx->dump_ctx); scc_ir_dump_value_linear(ctx, value->data.global_alloc.value); return; case SCC_IR_VALUE_TAG_CONST_ARRAY: @@ -699,6 +708,7 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref, void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) { for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) { + scc_tree_dump_begin_line(ctx->dump_ctx); scc_ir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i)); } for (usize i = 0; i < scc_vec_size(ctx->cprog->func_decls); i++) { diff --git a/libs/ir2mcode/include/frame_alloc.h b/libs/ir2mcode/include/frame_alloc.h new file mode 100644 index 0000000..1632cb0 --- /dev/null +++ b/libs/ir2mcode/include/frame_alloc.h @@ -0,0 +1,21 @@ +#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/frame_manager.h b/libs/ir2mcode/include/frame_manager.h deleted file mode 100644 index 917aec0..0000000 --- a/libs/ir2mcode/include/frame_manager.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __SCC_FRAME_MANAGER_H__ -#define __SCC_FRAME_MANAGER_H__ - -typedef struct frame_manager frame_manager_t; - -// 初始化帧管理器,传入 ABI 参数(影子空间大小、栈对齐等) -void frame_manager_init(frame_manager_t *fm, int shadow_space, int align); - -// 分配一个栈槽(用于局部变量或临时值),返回虚拟槽索引(从0开始) -int frame_alloc_slot(frame_manager_t *fm, int size); - -// 分配一个保存的寄存器槽(用于被调用者保存的寄存器),返回虚拟槽索引 -int frame_alloc_saved_reg(frame_manager_t *fm, int reg_width); - -// 计算最终栈帧总大小(已对齐) -int frame_total_size(frame_manager_t *fm); - -// 将虚拟槽索引转换为相对于 RBP 的偏移(正数,表示从 RBP 向下的距离) -int frame_slot_offset(frame_manager_t *fm, int slot_idx); - -// 获取影子空间大小(固定) -int frame_shadow_space(frame_manager_t *fm); - -// 获取保存寄存器区域的总大小 -int frame_saved_reg_size(frame_manager_t *fm); - -#endif /* __SCC_FRAME_MANAGER_H__ */ diff --git a/libs/ir2mcode/include/reg_alloc.h b/libs/ir2mcode/include/reg_alloc.h index 5f3cf1b..1d90d93 100644 --- a/libs/ir2mcode/include/reg_alloc.h +++ b/libs/ir2mcode/include/reg_alloc.h @@ -1,6 +1,7 @@ #ifndef __SCC_REG_ALLOC_H__ #define __SCC_REG_ALLOC_H__ +#include "frame_alloc.h" #include #include #include @@ -18,33 +19,59 @@ typedef enum { typedef struct { scc_reg_kind_t kind; - usize idx; + 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 scc_hashtable_t *(*scc_reg_alloc_func_t)( - scc_reg_alloc_t *ctx, ///< @param [in] 上下文 - scc_ir_func_t *func ///< @param [in] 待处理的 IR 函数 -); +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_ir_module_t *ir_module; ///< IR存储节点 - scc_hashtable_t node_ref2reg_loc; ///< 输出结果哈希表 - scc_reg_loc_vec_t reg_loc_vec; - int gpr_caller_saved; ///< 函数可以随意修改,调用者如果在意需自行保护. - int gpr_callee_saved; ///< 函数必须保护这些寄存器的值. + 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; - int alloc_stack_size; - int init_stack_size; } scc_reg_alloc_t; -#define scc_reg_alloc(ctx, func) ((ctx)->reg_alloc_func(ctx, func)) - -void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t func, +void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t strategy, scc_ir_module_t *ir_module); -scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, - scc_ir_func_t *func); +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/src/frame_alloc_win64.c b/libs/ir2mcode/src/frame_alloc_win64.c new file mode 100644 index 0000000..465c9a8 --- /dev/null +++ b/libs/ir2mcode/src/frame_alloc_win64.c @@ -0,0 +1,160 @@ +#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); + } + + slot->offset = current_offset; + scc_hashtable_set(&self->offset_cache, (void *)(intptr_t)slot->slot_id, + (void *)(intptr_t)slot->offset); + + current_offset -= slot->size; + } + + 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/frame_manager.c b/libs/ir2mcode/src/frame_manager.c deleted file mode 100644 index 2f7fffc..0000000 --- a/libs/ir2mcode/src/frame_manager.c +++ /dev/null @@ -1,50 +0,0 @@ -// frame_manager.c -#include "frame_manager.h" -#include -#include - -struct frame_manager { - int shadow_space; // 影子空间大小(字节) - int saved_reg_size; // 已分配的保存寄存器区域大小 - int local_size; // 已分配的局部变量区域大小 - int align; // 栈对齐要求 -}; - -void frame_manager_init(frame_manager_t *fm, int shadow_space, int align) { - fm->shadow_space = shadow_space; - fm->saved_reg_size = 0; - fm->local_size = 0; - fm->align = align; -} - -int frame_alloc_slot(frame_manager_t *fm, int size) { - int offset = fm->local_size; - fm->local_size += size; - return offset; // 返回虚拟偏移(从0开始) -} - -int frame_alloc_saved_reg(frame_manager_t *fm, int reg_width) { - int offset = fm->saved_reg_size; - fm->saved_reg_size += reg_width; - return offset; -} - -int frame_total_size(frame_manager_t *fm) { - int total = fm->shadow_space + fm->saved_reg_size + fm->local_size; - // 对齐到 align 字节 - return (total + fm->align - 1) & ~(fm->align - 1); -} - -int frame_slot_offset(frame_manager_t *fm, int slot_idx) { - // 布局: RBP 指向保存的 RBP,向下依次是: - // [影子空间] [保存寄存器区] [局部变量区] - // 局部变量区的起始地址 = RBP - (8 + shadow_space + saved_reg_size) - // 其中 8 是 push rbp 占用的空间(返回地址在 RBP+8,但 RBP 本身指向保存的 - // RBP) - int base = 8 + fm->shadow_space + fm->saved_reg_size; - return base + slot_idx; // 返回正数,表示从 RBP 向下的字节数 -} - -int frame_shadow_space(frame_manager_t *fm) { return fm->shadow_space; } - -int frame_saved_reg_size(frame_manager_t *fm) { return fm->saved_reg_size; } diff --git a/libs/ir2mcode/src/ir2amd64.c b/libs/ir2mcode/src/ir2amd64.c index bc03820..87b3ef1 100644 --- a/libs/ir2mcode/src/ir2amd64.c +++ b/libs/ir2mcode/src/ir2amd64.c @@ -14,23 +14,51 @@ static bool scc_type_is_signed(scc_ir_type_t *type) { 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 *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref); - if (node == nullptr) { - LOG_FATAL("invalid node ref"); + 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 (node->tag) { + switch (value->tag) { case SCC_IR_VALUE_TAG_CONST_INT: scc_ir_type_t *type = - scc_ir_module_get_type(GET_MODULE(ctx), node->type); + scc_ir_module_get_type(GET_MODULE(ctx), value->type); Assert(type != 0); - Assert(type->tag == SCC_IR_TYPE_u32 || type->tag == SCC_IR_TYPE_i32); - *loc = (scc_reg_loc_t){ - .kind = SCC_REG_KIND_IMM, - .idx = (usize)node->data.const_int.int32, - }; + 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: @@ -39,18 +67,7 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: TODO(); break; - case SCC_IR_VALUE_TAG_FUNC_ARG_REF: { - scc_ir_type_t *type = - scc_ir_module_get_type(GET_MODULE(ctx), node->type); - Assert(type != 0); - scc_reg_loc_t arg_loc; - // arg_loc.kind = SCC_REG_KIND_FUNC_ARG; - // arg_loc.idx = node->data.arg_ref.idx; - arg_loc.kind = SCC_REG_KIND_STACK_ADDR; - arg_loc.idx = 8 * node->data.arg_ref.idx; - *loc = arg_loc; - return; - } + case SCC_IR_VALUE_TAG_FUNC_ARG_REF: case SCC_IR_VALUE_TAG_ALLOC: default: idx = (usize)scc_hashtable_get(ctx->noderef2regloc, @@ -58,62 +75,65 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc, break; } - Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.reg_loc_vec)); - *loc = scc_vec_at(ctx->reg_alloc.reg_loc_vec, idx - 1); + 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_mcode_t *mcode, scc_reg_loc_t *loc, int reg) { +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->idx != reg) { - scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->idx); + 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: - // FIXME -8 for rdp - scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP, - -loc->idx - 8); - break; - case SCC_REG_KIND_IMM: - scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32 + 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: // 将栈地址加载到寄存器(取地址) - // FIXME -8 for rdp - scc_mcode_amd64_lea_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP, - -loc->idx - 8); + 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_mcode_t *mcode, scc_reg_loc_t *loc, +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->idx != reg) { - scc_mcode_amd64_mov_r64_r64(mcode, loc->idx, reg); + if (loc->data.gpr_idx != reg) { + scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg); } break; case SCC_REG_KIND_STACK: - // FIXME -8 for rdp - scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8, - reg); + 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; - case SCC_REG_KIND_STACK_ADDR: - // 将寄存器的值存储到栈地址 - // FIXME -8 for rdp - scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8, - reg); - break; default: - LOG_FATAL("unsupported location"); + Panic("unsupported location %d", loc->kind); break; } } @@ -127,15 +147,49 @@ 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 *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref); - if (node == nullptr) { - LOG_ERROR("invalid node ref"); + 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 (node->tag) { + 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 node type: %d", node->tag); + LOG_FATAL("Unsupported value type: %d", value->tag); break; ///< 函数参数引用 case SCC_IR_VALUE_TAG_FUNC_ARG_REF: @@ -148,16 +202,16 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, break; ///< 加载数据 case SCC_IR_VALUE_TAG_LOAD: { - // node->data.load.target + // value->data.load.target scc_reg_loc_t from; scc_reg_loc_t to; - parse_location(ctx, &from, node->data.load.target); + parse_location(ctx, &from, value->data.load.target); parse_location(ctx, &to, node_ref); - load_value_to_reg(&ctx->sect_mcode, &from, SCC_AMD64_RCX); + 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), node->data.load.target); + 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); @@ -195,23 +249,23 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, SCC_AMD64_RCX); } // 存储结果 - store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX); + 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, node->data.store.value); - parse_location(ctx, &addr_loc, node->data.store.target); + parse_location(ctx, &val_loc, value->data.store.value); + parse_location(ctx, &addr_loc, value->data.store.target); // 将值加载到 RAX - load_value_to_reg(&ctx->sect_mcode, &val_loc, SCC_AMD64_RAX); + load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX); // 将目标地址加载到 RCX - load_value_to_reg(&ctx->sect_mcode, &addr_loc, SCC_AMD64_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), node->data.store.target); + 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); @@ -238,7 +292,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, parse_location(ctx, &loc_res, node_ref); scc_ir_value_t *src_addr = scc_ir_module_get_value( - GET_MODULE(ctx), node->data.get_ptr.src_addr); + GET_MODULE(ctx), value->data.get_ptr.src_addr); Assert(src_addr != nullptr); if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) { @@ -254,25 +308,24 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, .reloc_type = SCCF_RELOC_TYPE_REL, .offset = scc_vec_size(ctx->sect_mcode.mcode) - 4, .addend = 4, - .sect_type = SCCF_SECT_DATA, + .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, node->data.get_ptr.src_addr); - // src_loc.kind 应为 SCC_REG_KIND_STACK_ADDR,idx 是虚拟偏移(正数) - scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX, - SCC_AMD64_RBP, -src_loc.idx - 8); + parse_location(ctx, &src_loc, value->data.get_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, node->data.get_ptr.src_addr); - load_value_to_reg(&ctx->sect_mcode, &src_loc, SCC_AMD64_RAX); + parse_location(ctx, &src_loc, value->data.get_ptr.src_addr); + load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); } - store_value_from_reg(&ctx->sect_mcode, &loc_res, SCC_AMD64_RAX); + store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX); break; } case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array) @@ -280,17 +333,17 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, ///< 二元运算 case SCC_IR_VALUE_TAG_OP: { scc_reg_loc_t loc_lhs; - parse_location(ctx, &loc_lhs, node->data.op.lhs); + parse_location(ctx, &loc_lhs, value->data.op.lhs); scc_reg_loc_t loc_rhs; - parse_location(ctx, &loc_rhs, node->data.op.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->sect_mcode, &loc_lhs, SCC_AMD64_RAX); + load_value_to_reg(ctx, &loc_lhs, SCC_AMD64_RAX); // 将右操作数加载到 RCX - load_value_to_reg(&ctx->sect_mcode, &loc_rhs, SCC_AMD64_RCX); - switch (node->data.op.op) { + 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; @@ -378,30 +431,30 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, SCC_AMD64_RAX); break; default: - LOG_FATAL("unknown op: %d", node->data.op.op); + LOG_FATAL("unknown op: %d", value->data.op.op); break; } // 将 RAX 中的结果存储到 res 位置 - store_value_from_reg(&ctx->sect_mcode, &loc_res, SCC_AMD64_RAX); + 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, node->data.branch.cond); + parse_location(ctx, &loc, value->data.branch.cond); // (void)loc; - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RAX); + 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)node->data.branch.true_bblock}; + (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)node->data.branch.false_bblock}; + (usize)value->data.branch.false_bblock}; scc_vec_push(*patches, patch_false); break; } @@ -409,8 +462,8 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, 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)node->data.jump.target_bblock}; + patch_t patch = { + .pos = pos, .target_bb_ref = (usize)value->data.jump.target_bblock}; scc_vec_push(*patches, patch); break; } @@ -425,16 +478,16 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, R8 不稳定的 第三个整型自变量 R9 不稳定的 第四个整型自变量 */ - scc_vec_foreach(node->data.call.args, i) { - parse_location(ctx, &loc, scc_vec_at(node->data.call.args, i)); + scc_vec_foreach(value->data.call.args, i) { + parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i)); if (i == 0) { - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RCX); + load_value_to_reg(ctx, &loc, SCC_AMD64_RCX); } else if (i == 1) { - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RDX); + load_value_to_reg(ctx, &loc, SCC_AMD64_RDX); } else if (i == 2) { - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_R8); + load_value_to_reg(ctx, &loc, SCC_AMD64_R8); } else if (i == 3) { - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_R9); + load_value_to_reg(ctx, &loc, SCC_AMD64_R9); } else { LOG_FATAL("not support more than 4 args"); } @@ -442,7 +495,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, } scc_ir_func_t *func = - scc_ir_module_get_func(GET_MODULE(ctx), node->data.call.callee); + scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee); if (!func) { LOG_ERROR("invalid function reference"); return; @@ -473,16 +526,16 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, 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->sect_mcode, &loc, SCC_AMD64_RAX); + store_value_from_reg(ctx, &loc, SCC_AMD64_RAX); } break; } ///< 函数返回 case SCC_IR_VALUE_TAG_RET: { - if (node->data.ret.ret_val) { + if (value->data.ret.ret_val) { scc_reg_loc_t loc; - parse_location(ctx, &loc, node->data.ret.ret_val); - load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RAX); + 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); @@ -490,7 +543,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref, break; } default: - LOG_FATAL("unknown node type: %d", node->tag); + LOG_FATAL("unknown value type: %d", value->tag); UNREACHABLE(); break; } @@ -511,14 +564,13 @@ 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 API instead - ctx->reg_alloc.init_stack_size = 8; - ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func); - // 对齐到 16 字节 - // FIXME - ctx->stack_size += 8; ///< for rbp - ctx->stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15; + // 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)); @@ -544,13 +596,13 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i); parse_location(ctx, &loc, node_ref); if (i == 0) { - store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RCX); + store_value_from_reg(ctx, &loc, SCC_AMD64_RCX); } else if (i == 1) { - store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RDX); + store_value_from_reg(ctx, &loc, SCC_AMD64_RDX); } else if (i == 2) { - store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_R8); + store_value_from_reg(ctx, &loc, SCC_AMD64_R8); } else if (i == 3) { - store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_R9); + store_value_from_reg(ctx, &loc, SCC_AMD64_R9); } else { LOG_FATAL("not support more than 4 args"); } @@ -589,11 +641,9 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) { } void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { - scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_with_stack, + scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_strategy_pure_stack, GET_MODULE(ctx)); - sccf_sect_data_t data_section; - scc_vec_init(data_section); 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)); @@ -612,7 +662,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, }; scc_vec_foreach(value->data.const_array.elements, j) { - scc_vec_push(data_section, + scc_vec_push(ctx->sect_data, scc_vec_at(value->data.const_array.elements, j)); } usize sym_idx = @@ -695,7 +745,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { scc_vec_size(ctx->sect_mcode.mcode)); sccf_builder_add_text_section(ctx->builder, &text_section); - sccf_builder_add_data_section(ctx->builder, &data_section); - // FIXME + sccf_builder_add_data_section(ctx->builder, &ctx->sect_data); + // FIXME maybe _entry and add crt ctx->builder->entry_symbol_name = "main"; } diff --git a/libs/ir2mcode/src/reg_alloc.c b/libs/ir2mcode/src/reg_alloc.c index d559a62..619a998 100644 --- a/libs/ir2mcode/src/reg_alloc.c +++ b/libs/ir2mcode/src/reg_alloc.c @@ -1,106 +1,74 @@ #include #include -u32 hash_func(const void *key) { return (usize)key; } -int equal_func(const void *key1, const void *key2) { +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 func, +void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t strategy, scc_ir_module_t *ir_module) { - ctx->gpr_caller_saved = 0; - ctx->gpr_callee_saved = 0; + ctx->frame_alloc = nullptr; ctx->ir_module = ir_module; - ctx->reg_alloc_func = func; - - ctx->alloc_stack_size = 0; - ctx->init_stack_size = 0; - scc_vec_init(ctx->reg_loc_vec); - scc_hashtable_init(&ctx->node_ref2reg_loc, hash_func, equal_func); + scc_hashtable_init(&ctx->node2loc, hash_func, equal_func); + scc_vec_init(ctx->loc_vec); + ctx->reg_alloc_func = strategy; } -scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, - scc_ir_func_t *func) { - ctx->alloc_stack_size = ctx->init_stack_size; - scc_hashtable_drop(&ctx->node_ref2reg_loc); - scc_vec_free(ctx->reg_loc_vec); - scc_vec_init(ctx->reg_loc_vec); +#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_FUNC_ARG; - loc.idx = i; - ctx->alloc_stack_size += 8; - scc_hashtable_set(&ctx->node_ref2reg_loc, (void *)(usize)node_ref, - (void *)scc_vec_size(ctx->reg_loc_vec)); - break; + 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); - Assert(bblock != nullptr); 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); - Assert(node != nullptr); - loc.kind = SCC_REG_KIND_UNDEF; + 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_PTR: - case SCC_IR_VALUE_TAG_GET_ELEM_PTR: { + case SCC_IR_VALUE_TAG_GET_ELEM_PTR: + case SCC_IR_VALUE_TAG_CALL: // 返回值 loc.kind = SCC_REG_KIND_STACK; - loc.idx = ctx->alloc_stack_size; - - ctx->alloc_stack_size += 8; - scc_vec_push(ctx->reg_loc_vec, loc); - scc_hashtable_set(&ctx->node_ref2reg_loc, - (void *)(usize)node_ref, - (void *)scc_vec_size(ctx->reg_loc_vec)); + 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: { - // 为 alloc 分配栈偏移,但不作为普通值存储 - loc.kind = - SCC_REG_KIND_STACK_ADDR; // 实际不需要存储到 reg_loc_vec scc_ir_type_t *type = scc_ir_module_get_type(ctx->ir_module, node->type); - Assert(type != nullptr); - loc.idx = ctx->alloc_stack_size; Assert(type->tag == SCC_IR_TYPE_PTR); - int len = scc_ir2mcode_type_width( - ctx->ir_module, - scc_ir_module_get_type(ctx->ir_module, - type->data.pointer.base)); - len = len % 8 == 0 ? len : len + 8 - len % 8; - ctx->alloc_stack_size += len; + 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); - // 记录偏移 - scc_vec_push(ctx->reg_loc_vec, loc); - scc_hashtable_set(&ctx->node_ref2reg_loc, - (void *)(usize)node_ref, - (void *)scc_vec_size(ctx->reg_loc_vec)); - break; - } - case SCC_IR_VALUE_TAG_CALL: { - // 处理返回值 - scc_ir_type_t *func_type = - scc_ir_module_get_type(ctx->ir_module, func->type); - Assert(func_type); - scc_ir_type_t *ret_type = scc_ir_module_get_type( - ctx->ir_module, func_type->data.function.ret_type); - if (ret_type && ret_type->tag != SCC_IR_TYPE_void) { - loc.kind = SCC_REG_KIND_STACK; - loc.idx = ctx->alloc_stack_size; - ctx->alloc_stack_size += 8; - scc_vec_push(ctx->reg_loc_vec, loc); - scc_hashtable_set(&ctx->node_ref2reg_loc, - (void *)(usize)node_ref, - (void *)scc_vec_size(ctx->reg_loc_vec)); - } + 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: @@ -108,5 +76,4 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx, } } } - return &ctx->node_ref2reg_loc; } diff --git a/libs/target/sccf2target/src/sccf2pe.c b/libs/target/sccf2target/src/sccf2pe.c index cb2fd63..13ee198 100644 --- a/libs/target/sccf2target/src/sccf2pe.c +++ b/libs/target/sccf2target/src/sccf2pe.c @@ -202,6 +202,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) { if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) { continue; } + Assert(reloc->sect_type == SCCF_SECT_CODE); sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx); const char *name = &scc_vec_at(strtab, sym->name_offset); diff --git a/runtime/scc_core/include/scc_core_macro.h b/runtime/scc_core/include/scc_core_macro.h index 49102d9..f313ed1 100644 --- a/runtime/scc_core/include/scc_core_macro.h +++ b/runtime/scc_core/include/scc_core_macro.h @@ -5,8 +5,10 @@ #define SCC_STR(str) _SCC_STR(str) #define SCC_ARRLEN(arr) (sizeof(arr) / sizeof(arr[0])) - #define SCC_FUNC +#define SCC_CALL(self, func, ...) (((self)->func)(self, ##__VA_ARGS__)) +#define SCC_TCALL(self, type, func, ...) \ + ((((type)(self))->func)(self, ##__VA_ARGS__)) #define scc_min(a, b) ((a) < (b) ? (a) : (b)) #define scc_max(a, b) ((a) > (b) ? (a) : (b))