feat(ir2mcode): 添加帧分配器框架和Windows 64位实现
添加了frame_alloc.h头文件定义帧分配器操作接口,实现了Windows 64位 平台的帧分配器实现,包括槽位分配、偏移计算和栈帧布局管理功能。 BREAKING CHANGE: 移除了旧的frame_manager.h接口,采用新的frame_alloc_ops_t 抽象接口。 fix(ast2ir): 修复字符串字面量表达式返回值问题 修复了AST到IR转换过程中字符串字面量表达式的处理,确保正确返回 创建的常量字符串值引用而非直接跳出。 fix(ir): 修复内置memcpy函数参数验证和类型比较逻辑 在IR构建器中为builtin_memcpy函数添加参数空指针检查,在类型比较 函数中添加未知类型的边界条件处理,增强系统稳定性。 refactor(ir2mcode): 重构寄存器分配器接口以支持帧分配器集成 修改寄存器分配器接口以接受帧分配器参数,统一节点到位置的映射表 命名,并提供便捷的栈大小和偏移获取接口。
This commit is contained in:
@@ -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: {
|
case SCC_AST_EXPR_STRING_LITERAL: {
|
||||||
// FIXME
|
// FIXME
|
||||||
scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme,
|
scc_ir_value_ref_t value =
|
||||||
scc_strlen(expr->literal.lexme));
|
scc_ir_builder_const_string(&ctx->builder, expr->literal.lexme,
|
||||||
|
scc_strlen(expr->literal.lexme));
|
||||||
if (is_lvalue)
|
if (is_lvalue)
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
return value;
|
||||||
}
|
}
|
||||||
case SCC_AST_EXPR_IDENTIFIER: {
|
case SCC_AST_EXPR_IDENTIFIER: {
|
||||||
if (expr->identifier._target == nullptr) {
|
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_ir_value_ref_t init_val_node =
|
||||||
scc_ast2ir_expr(ctx, decl->var.init, false);
|
scc_ast2ir_expr(ctx, decl->var.init, false);
|
||||||
|
Assert(init_val_node != nullptr);
|
||||||
|
|
||||||
// FIXME array auto calucate size
|
// FIXME array auto calucate size
|
||||||
scc_ir_type_t *ir_type =
|
scc_ir_type_t *ir_type =
|
||||||
scc_ir_module_get_type(ctx->builder.ctx.module, ir_type_ref);
|
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) {
|
if (ir_type->tag == SCC_IR_TYPE_ARRAY) {
|
||||||
scc_ast_expr_t *init_expr = decl->var.init;
|
if (ir_type->data.array.len == 0) {
|
||||||
if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) {
|
scc_ast_expr_t *init_expr = decl->var.init;
|
||||||
Panic("TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND");
|
if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) {
|
||||||
} else if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) {
|
Panic(
|
||||||
ir_type->data.array.len =
|
"TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND");
|
||||||
scc_strlen(init_expr->literal.lexme) + 1;
|
} 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_const_int_t len = {.int64 = ir_type->data.array.len};
|
||||||
scc_ir_value_ref_t len_ref = scc_ir_builder_const_int(
|
scc_ir_value_ref_t len_ref = scc_ir_builder_const_int(
|
||||||
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder), len);
|
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder),
|
||||||
scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node,
|
len);
|
||||||
init_val_node, len_ref);
|
scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node,
|
||||||
} else {
|
init_val_node, len_ref);
|
||||||
Panic("unknown init expr in array decl");
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_DECL_FUNC: {
|
case SCC_AST_DECL_FUNC: {
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ static inline scc_ir_value_ref_t
|
|||||||
scc_ir_builder_builtin_memcpy(scc_ir_builder_t *builder,
|
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 dest, scc_ir_value_ref_t src,
|
||||||
scc_ir_value_ref_t len) {
|
scc_ir_value_ref_t len) {
|
||||||
|
Assert(builder && src && dest && len);
|
||||||
scc_ir_value_t value;
|
scc_ir_value_t value;
|
||||||
scc_ir_value_init(&value, nullptr, SCC_IR_VALUE_TAG_BUILTIN);
|
scc_ir_value_init(&value, nullptr, SCC_IR_VALUE_TAG_BUILTIN);
|
||||||
value.type = scc_ir_builder_type_void(builder); // memcpy 返回 void*
|
value.type = scc_ir_builder_type_void(builder); // memcpy 返回 void*
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ static u32 hash_type(const void *_key) {
|
|||||||
}
|
}
|
||||||
static int cmp_type(const void *_key1, const void *_key2) {
|
static int cmp_type(const void *_key1, const void *_key2) {
|
||||||
const scc_ir_type_t *key1 = _key1, *key2 = _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不同
|
// tag不同
|
||||||
if (key1->tag != key2->tag) {
|
if (key1->tag != key2->tag) {
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -481,9 +481,17 @@ void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx,
|
|||||||
|
|
||||||
switch (value->tag) {
|
switch (value->tag) {
|
||||||
case SCC_IR_VALUE_TAG_BUILTIN: {
|
case SCC_IR_VALUE_TAG_BUILTIN: {
|
||||||
|
scc_tree_dump_append(ctx->dump_ctx, "@scc::");
|
||||||
switch (value->data.builtin.tag) {
|
switch (value->data.builtin.tag) {
|
||||||
case SCC_IR_BUILTIN_TAG_MEMCPY:
|
case SCC_IR_BUILTIN_TAG_MEMCPY:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "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;
|
break;
|
||||||
case SCC_IR_BUILTIN_TAG_MEMSET:
|
case SCC_IR_BUILTIN_TAG_MEMSET:
|
||||||
scc_tree_dump_append(ctx->dump_ctx, "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);
|
value->data.arg_ref.idx);
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
|
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);
|
scc_ir_dump_value_linear(ctx, value->data.global_alloc.value);
|
||||||
return;
|
return;
|
||||||
case SCC_IR_VALUE_TAG_CONST_ARRAY:
|
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) {
|
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++) {
|
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));
|
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++) {
|
for (usize i = 0; i < scc_vec_size(ctx->cprog->func_decls); i++) {
|
||||||
|
|||||||
21
libs/ir2mcode/include/frame_alloc.h
Normal file
21
libs/ir2mcode/include/frame_alloc.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef __SCC_FRAME_ALLOC_H__
|
||||||
|
#define __SCC_FRAME_ALLOC_H__
|
||||||
|
|
||||||
|
#include <scc_ir.h>
|
||||||
|
|
||||||
|
typedef struct scc_frame_alloc_ops scc_frame_alloc_ops_t;
|
||||||
|
struct scc_frame_alloc_ops {
|
||||||
|
/// maybe have direct function to new
|
||||||
|
scc_frame_alloc_ops_t *(*new)(scc_ir_func_t *func);
|
||||||
|
int (*drop)(scc_frame_alloc_ops_t *alloc);
|
||||||
|
|
||||||
|
int (*alloc_spill_slot)(scc_frame_alloc_ops_t *frame, int size, int align);
|
||||||
|
int (*alloc_local_slot)(scc_frame_alloc_ops_t *frame, int size, int align,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
void (*finalize)(scc_frame_alloc_ops_t *frame);
|
||||||
|
int (*get_slot_offset)(scc_frame_alloc_ops_t *frame, int slot_id);
|
||||||
|
int (*get_frame_size)(scc_frame_alloc_ops_t *frame);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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__ */
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef __SCC_REG_ALLOC_H__
|
#ifndef __SCC_REG_ALLOC_H__
|
||||||
#define __SCC_REG_ALLOC_H__
|
#define __SCC_REG_ALLOC_H__
|
||||||
|
|
||||||
|
#include "frame_alloc.h"
|
||||||
#include <scc_core.h>
|
#include <scc_core.h>
|
||||||
#include <scc_ir.h>
|
#include <scc_ir.h>
|
||||||
#include <scc_utils.h>
|
#include <scc_utils.h>
|
||||||
@@ -18,33 +19,59 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_reg_kind_t kind;
|
scc_reg_kind_t kind;
|
||||||
usize idx;
|
union {
|
||||||
|
usize data;
|
||||||
|
int slot_idx;
|
||||||
|
int gpr_idx;
|
||||||
|
int fpr_idx;
|
||||||
|
} data;
|
||||||
} scc_reg_loc_t;
|
} scc_reg_loc_t;
|
||||||
typedef SCC_VEC(scc_reg_loc_t) scc_reg_loc_vec_t;
|
typedef SCC_VEC(scc_reg_loc_t) scc_reg_loc_vec_t;
|
||||||
|
|
||||||
struct scc_reg_alloc;
|
struct scc_reg_alloc;
|
||||||
typedef struct scc_reg_alloc scc_reg_alloc_t;
|
typedef struct scc_reg_alloc scc_reg_alloc_t;
|
||||||
typedef scc_hashtable_t *(*scc_reg_alloc_func_t)(
|
typedef void (*scc_reg_alloc_func_t)(scc_reg_alloc_t *ctx, scc_ir_func_t *func,
|
||||||
scc_reg_alloc_t *ctx, ///< @param [in] 上下文
|
scc_frame_alloc_ops_t *frame_alloc);
|
||||||
scc_ir_func_t *func ///< @param [in] 待处理的 IR 函数
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef struct scc_reg_alloc {
|
typedef struct scc_reg_alloc {
|
||||||
scc_ir_module_t *ir_module; ///< IR存储节点
|
scc_frame_alloc_ops_t *frame_alloc;
|
||||||
scc_hashtable_t node_ref2reg_loc; ///< 输出结果哈希表
|
scc_ir_module_t *ir_module; ///< IR存储节点
|
||||||
scc_reg_loc_vec_t reg_loc_vec;
|
scc_hashtable_t node2loc; ///< 输出结果哈希表
|
||||||
int gpr_caller_saved; ///< 函数可以随意修改,调用者如果在意需自行保护.
|
scc_reg_loc_vec_t loc_vec;
|
||||||
int gpr_callee_saved; ///< 函数必须保护这些寄存器的值.
|
|
||||||
scc_reg_alloc_func_t reg_alloc_func;
|
scc_reg_alloc_func_t reg_alloc_func;
|
||||||
int alloc_stack_size;
|
|
||||||
int init_stack_size;
|
|
||||||
} scc_reg_alloc_t;
|
} 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 strategy,
|
||||||
|
|
||||||
void scc_reg_alloc_init(scc_reg_alloc_t *ctx, scc_reg_alloc_func_t func,
|
|
||||||
scc_ir_module_t *ir_module);
|
scc_ir_module_t *ir_module);
|
||||||
scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
|
static inline scc_hashtable_t *
|
||||||
scc_ir_func_t *func);
|
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__ */
|
#endif /* __SCC_REG_ALLOC_H__ */
|
||||||
|
|||||||
160
libs/ir2mcode/src/frame_alloc_win64.c
Normal file
160
libs/ir2mcode/src/frame_alloc_win64.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
#include <frame_alloc.h>
|
||||||
|
#include <scc_utils.h>
|
||||||
|
#include <type_manager.h>
|
||||||
|
|
||||||
|
static const int WIN64_DEFAULT_ALIGN = 8;
|
||||||
|
static const int WIN64_STACK_ALIGN = 16;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
int align;
|
||||||
|
int slot_id;
|
||||||
|
int offset; // 最终计算的偏移(负值)
|
||||||
|
} win64_slot_t;
|
||||||
|
|
||||||
|
typedef SCC_VEC(win64_slot_t) win64_slot_vec_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
scc_frame_alloc_ops_t base;
|
||||||
|
scc_ir_func_t *func;
|
||||||
|
win64_slot_vec_t slots; // 所有已分配的槽位
|
||||||
|
scc_hashtable_t offset_cache; // slot_id -> offset
|
||||||
|
int stack_size; // 最终对齐后的栈帧大小
|
||||||
|
int finalized; // 是否已调用 finalize
|
||||||
|
} win64_alloc_t;
|
||||||
|
|
||||||
|
/* ---------- 辅助函数 ---------- */
|
||||||
|
static u32 hash_ptr(const void *key) { return (u32)(uintptr_t)key; }
|
||||||
|
|
||||||
|
static int cmp_ptr(const void *a, const void *b) {
|
||||||
|
return (uintptr_t)a != (uintptr_t)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 槽位分配 ---------- */
|
||||||
|
static int win64_alloc_slot_common(win64_alloc_t *self, int size, int align) {
|
||||||
|
if (self->finalized) {
|
||||||
|
Panic("frame_alloc: cannot allocate after finalize");
|
||||||
|
}
|
||||||
|
win64_slot_t slot;
|
||||||
|
slot.size = (size <= 0) ? WIN64_DEFAULT_ALIGN : size;
|
||||||
|
slot.align = (align <= 0) ? WIN64_DEFAULT_ALIGN : align;
|
||||||
|
// 对齐不能小于自然对齐
|
||||||
|
if (slot.align < 1)
|
||||||
|
slot.align = 1;
|
||||||
|
slot.slot_id = (int)scc_vec_size(self->slots);
|
||||||
|
slot.offset = 0; // 暂未计算
|
||||||
|
scc_vec_push(self->slots, slot);
|
||||||
|
return slot.slot_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int win64_alloc_spill_slot(scc_frame_alloc_ops_t *ops, int size,
|
||||||
|
int align) {
|
||||||
|
win64_alloc_t *self = (win64_alloc_t *)ops;
|
||||||
|
return win64_alloc_slot_common(self, size, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int win64_alloc_local_slot(scc_frame_alloc_ops_t *ops, int size,
|
||||||
|
int align, const char *name) {
|
||||||
|
(void)name; // 本实现不记录名称
|
||||||
|
return win64_alloc_spill_slot(ops, size, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- 最终布局计算 ---------- */
|
||||||
|
static void win64_finalize(scc_frame_alloc_ops_t *ops) {
|
||||||
|
win64_alloc_t *self = (win64_alloc_t *)ops;
|
||||||
|
if (self->finalized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int current_offset = -WIN64_DEFAULT_ALIGN; // 从 -8 开始
|
||||||
|
|
||||||
|
for (usize i = 0; i < scc_vec_size(self->slots); i++) {
|
||||||
|
win64_slot_t *slot = &scc_vec_at(self->slots, i);
|
||||||
|
int align = slot->align;
|
||||||
|
|
||||||
|
// 向下对齐到 align 的倍数(current_offset 为负数)
|
||||||
|
int rem = ((-current_offset) % align);
|
||||||
|
if (rem != 0) {
|
||||||
|
current_offset -= (align - rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// frame_manager.c
|
|
||||||
#include "frame_manager.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
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; }
|
|
||||||
@@ -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,
|
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
||||||
scc_ir_value_ref_t node_ref) {
|
scc_ir_value_ref_t node_ref) {
|
||||||
Assert(ctx != nullptr && loc != nullptr);
|
Assert(ctx != nullptr && loc != nullptr);
|
||||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||||
if (node == nullptr) {
|
if (value == nullptr) {
|
||||||
LOG_FATAL("invalid node ref");
|
LOG_FATAL("invalid value ref");
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
usize idx = 0;
|
usize idx = 0;
|
||||||
switch (node->tag) {
|
switch (value->tag) {
|
||||||
case SCC_IR_VALUE_TAG_CONST_INT:
|
case SCC_IR_VALUE_TAG_CONST_INT:
|
||||||
scc_ir_type_t *type =
|
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 != 0);
|
||||||
Assert(type->tag == SCC_IR_TYPE_u32 || type->tag == SCC_IR_TYPE_i32);
|
switch (type->tag) {
|
||||||
*loc = (scc_reg_loc_t){
|
case SCC_IR_TYPE_u8:
|
||||||
.kind = SCC_REG_KIND_IMM,
|
case SCC_IR_TYPE_i8:
|
||||||
.idx = (usize)node->data.const_int.int32,
|
*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;
|
return;
|
||||||
case SCC_IR_VALUE_TAG_CONST_UINT:
|
case SCC_IR_VALUE_TAG_CONST_UINT:
|
||||||
case SCC_IR_VALUE_TAG_CONST_FLOAT:
|
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:
|
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
|
||||||
TODO();
|
TODO();
|
||||||
break;
|
break;
|
||||||
case SCC_IR_VALUE_TAG_FUNC_ARG_REF: {
|
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_ALLOC:
|
case SCC_IR_VALUE_TAG_ALLOC:
|
||||||
default:
|
default:
|
||||||
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.reg_loc_vec));
|
Assert(idx > 0 && idx <= scc_vec_size(ctx->reg_alloc.loc_vec));
|
||||||
*loc = scc_vec_at(ctx->reg_alloc.reg_loc_vec, idx - 1);
|
*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) {
|
switch (loc->kind) {
|
||||||
case SCC_REG_KIND_GPR:
|
case SCC_REG_KIND_GPR:
|
||||||
if (loc->idx != reg) {
|
if (loc->data.gpr_idx != reg) {
|
||||||
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->idx);
|
scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->data.gpr_idx);
|
||||||
} else {
|
} else {
|
||||||
TODO();
|
TODO();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_REG_KIND_STACK:
|
case SCC_REG_KIND_STACK:
|
||||||
// FIXME -8 for rdp
|
scc_mcode_amd64_mov_r64_m64_disp32(
|
||||||
scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP,
|
mcode, reg, SCC_AMD64_RBP,
|
||||||
-loc->idx - 8);
|
scc_reg_stack_offset(&ctx->reg_alloc, loc));
|
||||||
break;
|
|
||||||
case SCC_REG_KIND_IMM:
|
|
||||||
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32
|
|
||||||
break;
|
break;
|
||||||
case SCC_REG_KIND_STACK_ADDR:
|
case SCC_REG_KIND_STACK_ADDR:
|
||||||
// 将栈地址加载到寄存器(取地址)
|
// 将栈地址加载到寄存器(取地址)
|
||||||
// FIXME -8 for rdp
|
scc_mcode_amd64_lea_r64_m64_disp32(
|
||||||
scc_mcode_amd64_lea_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP,
|
mcode, reg, SCC_AMD64_RBP,
|
||||||
-loc->idx - 8);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_FATAL("unsupported location");
|
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) {
|
int reg) {
|
||||||
|
scc_mcode_t *mcode = &ctx->sect_mcode;
|
||||||
switch (loc->kind) {
|
switch (loc->kind) {
|
||||||
case SCC_REG_KIND_GPR:
|
case SCC_REG_KIND_GPR:
|
||||||
if (loc->idx != reg) {
|
if (loc->data.gpr_idx != reg) {
|
||||||
scc_mcode_amd64_mov_r64_r64(mcode, loc->idx, reg);
|
scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SCC_REG_KIND_STACK:
|
case SCC_REG_KIND_STACK:
|
||||||
// FIXME -8 for rdp
|
scc_mcode_amd64_mov_m64_disp32_r64(
|
||||||
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8,
|
mcode, SCC_AMD64_RBP, scc_reg_stack_offset(&ctx->reg_alloc, loc),
|
||||||
reg);
|
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;
|
break;
|
||||||
case SCC_REG_KIND_IMM:
|
case SCC_REG_KIND_IMM:
|
||||||
LOG_FATAL("cannot store to immediate");
|
LOG_FATAL("cannot store to immediate");
|
||||||
break;
|
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:
|
default:
|
||||||
LOG_FATAL("unsupported location");
|
Panic("unsupported location %d", loc->kind);
|
||||||
break;
|
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,
|
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||||
patch_vec_t *patches) {
|
patch_vec_t *patches) {
|
||||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||||
if (node == nullptr) {
|
if (value == nullptr) {
|
||||||
LOG_ERROR("invalid node ref");
|
LOG_ERROR("invalid value ref");
|
||||||
return;
|
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: ///< 类型转换
|
case SCC_IR_VALUE_TAG_CONV: ///< 类型转换
|
||||||
LOG_FATAL("Unsupported node type: %d", node->tag);
|
LOG_FATAL("Unsupported value type: %d", value->tag);
|
||||||
break;
|
break;
|
||||||
///< 函数参数引用
|
///< 函数参数引用
|
||||||
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
|
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;
|
break;
|
||||||
///< 加载数据
|
///< 加载数据
|
||||||
case SCC_IR_VALUE_TAG_LOAD: {
|
case SCC_IR_VALUE_TAG_LOAD: {
|
||||||
// node->data.load.target
|
// value->data.load.target
|
||||||
scc_reg_loc_t from;
|
scc_reg_loc_t from;
|
||||||
scc_reg_loc_t to;
|
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);
|
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(
|
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(
|
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
||||||
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
|
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);
|
SCC_AMD64_RCX);
|
||||||
}
|
}
|
||||||
// 存储结果
|
// 存储结果
|
||||||
store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX);
|
store_value_from_reg(ctx, &to, SCC_AMD64_RAX);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
///< 存储数据
|
///< 存储数据
|
||||||
case SCC_IR_VALUE_TAG_STORE: {
|
case SCC_IR_VALUE_TAG_STORE: {
|
||||||
scc_reg_loc_t val_loc, addr_loc;
|
scc_reg_loc_t val_loc, addr_loc;
|
||||||
parse_location(ctx, &val_loc, node->data.store.value);
|
parse_location(ctx, &val_loc, value->data.store.value);
|
||||||
parse_location(ctx, &addr_loc, node->data.store.target);
|
parse_location(ctx, &addr_loc, value->data.store.target);
|
||||||
|
|
||||||
// 将值加载到 RAX
|
// 将值加载到 RAX
|
||||||
load_value_to_reg(&ctx->sect_mcode, &val_loc, SCC_AMD64_RAX);
|
load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX);
|
||||||
// 将目标地址加载到 RCX
|
// 将目标地址加载到 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(
|
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(
|
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
||||||
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
|
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);
|
parse_location(ctx, &loc_res, node_ref);
|
||||||
|
|
||||||
scc_ir_value_t *src_addr = scc_ir_module_get_value(
|
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);
|
Assert(src_addr != nullptr);
|
||||||
|
|
||||||
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
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,
|
.reloc_type = SCCF_RELOC_TYPE_REL,
|
||||||
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
|
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
|
||||||
.addend = 4,
|
.addend = 4,
|
||||||
.sect_type = SCCF_SECT_DATA,
|
.sect_type = SCCF_SECT_CODE,
|
||||||
.sym_idx = sym_idx,
|
.sym_idx = sym_idx,
|
||||||
});
|
});
|
||||||
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
||||||
// 栈上变量:地址为 rbp - offset
|
// 栈上变量:地址为 rbp - offset
|
||||||
scc_reg_loc_t src_loc;
|
scc_reg_loc_t src_loc;
|
||||||
parse_location(ctx, &src_loc, node->data.get_ptr.src_addr);
|
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
|
||||||
// src_loc.kind 应为 SCC_REG_KIND_STACK_ADDR,idx 是虚拟偏移(正数)
|
src_loc.kind = SCC_REG_KIND_STACK_ADDR;
|
||||||
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
|
load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX);
|
||||||
SCC_AMD64_RBP, -src_loc.idx - 8);
|
|
||||||
} else {
|
} else {
|
||||||
// 其他情况(如链式 getptr):源地址值已经存储在某个位置,直接加载到
|
// 其他情况(如链式 getptr):源地址值已经存储在某个位置,直接加载到
|
||||||
// RAX
|
// RAX
|
||||||
scc_reg_loc_t src_loc;
|
scc_reg_loc_t src_loc;
|
||||||
parse_location(ctx, &src_loc, node->data.get_ptr.src_addr);
|
parse_location(ctx, &src_loc, value->data.get_ptr.src_addr);
|
||||||
load_value_to_reg(&ctx->sect_mcode, &src_loc, SCC_AMD64_RAX);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array)
|
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: {
|
case SCC_IR_VALUE_TAG_OP: {
|
||||||
scc_reg_loc_t loc_lhs;
|
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;
|
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;
|
scc_reg_loc_t loc_res;
|
||||||
parse_location(ctx, &loc_res, node_ref);
|
parse_location(ctx, &loc_res, node_ref);
|
||||||
|
|
||||||
// 将左操作数加载到 RAX(临时结果寄存器)
|
// 将左操作数加载到 RAX(临时结果寄存器)
|
||||||
load_value_to_reg(&ctx->sect_mcode, &loc_lhs, SCC_AMD64_RAX);
|
load_value_to_reg(ctx, &loc_lhs, SCC_AMD64_RAX);
|
||||||
// 将右操作数加载到 RCX
|
// 将右操作数加载到 RCX
|
||||||
load_value_to_reg(&ctx->sect_mcode, &loc_rhs, SCC_AMD64_RCX);
|
load_value_to_reg(ctx, &loc_rhs, SCC_AMD64_RCX);
|
||||||
switch (node->data.op.op) {
|
switch (value->data.op.op) {
|
||||||
case SCC_IR_OP_EMPTY:
|
case SCC_IR_OP_EMPTY:
|
||||||
Panic("unsupported empty op");
|
Panic("unsupported empty op");
|
||||||
break;
|
break;
|
||||||
@@ -378,30 +431,30 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|||||||
SCC_AMD64_RAX);
|
SCC_AMD64_RAX);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_FATAL("unknown op: %d", node->data.op.op);
|
LOG_FATAL("unknown op: %d", value->data.op.op);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// 将 RAX 中的结果存储到 res 位置
|
// 将 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;
|
break;
|
||||||
}
|
}
|
||||||
///< 有条件分支
|
///< 有条件分支
|
||||||
case SCC_IR_VALUE_TAG_BRANCH: {
|
case SCC_IR_VALUE_TAG_BRANCH: {
|
||||||
scc_reg_loc_t loc;
|
scc_reg_loc_t loc;
|
||||||
parse_location(ctx, &loc, node->data.branch.cond);
|
parse_location(ctx, &loc, value->data.branch.cond);
|
||||||
// (void)loc;
|
// (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_cmp_r64_imm32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
|
||||||
|
|
||||||
scc_mcode_amd64_jcc_rel32(&ctx->sect_mcode, SCC_AMD64_COND_NE, 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),
|
patch_t patch_true = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
|
||||||
.target_bb_ref =
|
.target_bb_ref =
|
||||||
(usize)node->data.branch.true_bblock};
|
(usize)value->data.branch.true_bblock};
|
||||||
scc_vec_push(*patches, patch_true);
|
scc_vec_push(*patches, patch_true);
|
||||||
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
|
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
|
||||||
patch_t patch_false = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
|
patch_t patch_false = {.pos = scc_vec_size(ctx->sect_mcode.mcode),
|
||||||
.target_bb_ref =
|
.target_bb_ref =
|
||||||
(usize)node->data.branch.false_bblock};
|
(usize)value->data.branch.false_bblock};
|
||||||
scc_vec_push(*patches, patch_false);
|
scc_vec_push(*patches, patch_false);
|
||||||
break;
|
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: {
|
case SCC_IR_VALUE_TAG_JUMP: {
|
||||||
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
|
scc_mcode_amd64_jmp_rel32(&ctx->sect_mcode, 0);
|
||||||
usize pos = scc_vec_size(ctx->sect_mcode.mcode);
|
usize pos = scc_vec_size(ctx->sect_mcode.mcode);
|
||||||
patch_t patch = {.pos = pos,
|
patch_t patch = {
|
||||||
.target_bb_ref = (usize)node->data.jump.target_bblock};
|
.pos = pos, .target_bb_ref = (usize)value->data.jump.target_bblock};
|
||||||
scc_vec_push(*patches, patch);
|
scc_vec_push(*patches, patch);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -425,16 +478,16 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|||||||
R8 不稳定的 第三个整型自变量
|
R8 不稳定的 第三个整型自变量
|
||||||
R9 不稳定的 第四个整型自变量
|
R9 不稳定的 第四个整型自变量
|
||||||
*/
|
*/
|
||||||
scc_vec_foreach(node->data.call.args, i) {
|
scc_vec_foreach(value->data.call.args, i) {
|
||||||
parse_location(ctx, &loc, scc_vec_at(node->data.call.args, i));
|
parse_location(ctx, &loc, scc_vec_at(value->data.call.args, i));
|
||||||
if (i == 0) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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 {
|
} else {
|
||||||
LOG_FATAL("not support more than 4 args");
|
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_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) {
|
if (!func) {
|
||||||
LOG_ERROR("invalid function reference");
|
LOG_ERROR("invalid function reference");
|
||||||
return;
|
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);
|
GET_MODULE(ctx), func_type->data.function.ret_type);
|
||||||
if (ret_type && ret_type->tag != SCC_IR_TYPE_void) {
|
if (ret_type && ret_type->tag != SCC_IR_TYPE_void) {
|
||||||
parse_location(ctx, &loc, node_ref);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
///< 函数返回
|
///< 函数返回
|
||||||
case SCC_IR_VALUE_TAG_RET: {
|
case SCC_IR_VALUE_TAG_RET: {
|
||||||
if (node->data.ret.ret_val) {
|
if (value->data.ret.ret_val) {
|
||||||
scc_reg_loc_t loc;
|
scc_reg_loc_t loc;
|
||||||
parse_location(ctx, &loc, node->data.ret.ret_val);
|
parse_location(ctx, &loc, value->data.ret.ret_val);
|
||||||
load_value_to_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RAX);
|
load_value_to_reg(ctx, &loc, SCC_AMD64_RAX);
|
||||||
}
|
}
|
||||||
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
|
scc_mcode_amd64_add_rsp_imm32(&ctx->sect_mcode, ctx->stack_size);
|
||||||
scc_mcode_amd64_pop_r64(&ctx->sect_mcode, SCC_AMD64_RBP);
|
scc_mcode_amd64_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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LOG_FATAL("unknown node type: %d", node->tag);
|
LOG_FATAL("unknown value type: %d", value->tag);
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -511,14 +564,13 @@ static int equal_func(const void *key1, const void *key2) {
|
|||||||
return (usize)key1 - (usize)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) {
|
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
||||||
// FIXME using API instead
|
// FIXME using other
|
||||||
ctx->reg_alloc.init_stack_size = 8;
|
ctx->noderef2regloc =
|
||||||
ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func);
|
scc_reg_alloc_run(&ctx->reg_alloc, func, scc_frame_alloc_win64_ops());
|
||||||
// 对齐到 16 字节
|
ctx->stack_size = scc_reg_stack_size(&ctx->reg_alloc);
|
||||||
// FIXME
|
Assert(ctx->noderef2regloc);
|
||||||
ctx->stack_size += 8; ///< for rbp
|
|
||||||
ctx->stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15;
|
|
||||||
|
|
||||||
usize bblock_cnt = scc_vec_size(func->bblocks);
|
usize bblock_cnt = scc_vec_size(func->bblocks);
|
||||||
usize *bblock_offsets = scc_calloc(bblock_cnt, sizeof(usize));
|
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);
|
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
||||||
parse_location(ctx, &loc, node_ref);
|
parse_location(ctx, &loc, node_ref);
|
||||||
if (i == 0) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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 {
|
} else {
|
||||||
LOG_FATAL("not support more than 4 args");
|
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) {
|
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));
|
GET_MODULE(ctx));
|
||||||
|
|
||||||
sccf_sect_data_t data_section;
|
|
||||||
scc_vec_init(data_section);
|
|
||||||
scc_vec_foreach(ctx->cprog->global_vals, i) {
|
scc_vec_foreach(ctx->cprog->global_vals, i) {
|
||||||
scc_ir_value_t *galloc = scc_ir_module_get_value(
|
scc_ir_value_t *galloc = scc_ir_module_get_value(
|
||||||
GET_MODULE(ctx), scc_vec_at(ctx->cprog->global_vals, i));
|
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,
|
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
|
||||||
};
|
};
|
||||||
scc_vec_foreach(value->data.const_array.elements, j) {
|
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));
|
scc_vec_at(value->data.const_array.elements, j));
|
||||||
}
|
}
|
||||||
usize sym_idx =
|
usize sym_idx =
|
||||||
@@ -695,7 +745,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
|||||||
scc_vec_size(ctx->sect_mcode.mcode));
|
scc_vec_size(ctx->sect_mcode.mcode));
|
||||||
sccf_builder_add_text_section(ctx->builder, &text_section);
|
sccf_builder_add_text_section(ctx->builder, &text_section);
|
||||||
|
|
||||||
sccf_builder_add_data_section(ctx->builder, &data_section);
|
sccf_builder_add_data_section(ctx->builder, &ctx->sect_data);
|
||||||
// FIXME
|
// FIXME maybe _entry and add crt
|
||||||
ctx->builder->entry_symbol_name = "main";
|
ctx->builder->entry_symbol_name = "main";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,106 +1,74 @@
|
|||||||
#include <reg_alloc.h>
|
#include <reg_alloc.h>
|
||||||
#include <type_manager.h>
|
#include <type_manager.h>
|
||||||
|
|
||||||
u32 hash_func(const void *key) { return (usize)key; }
|
static u32 hash_func(const void *key) { return (usize)key; }
|
||||||
int equal_func(const void *key1, const void *key2) {
|
static int equal_func(const void *key1, const void *key2) {
|
||||||
return (usize)key1 - (usize)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) {
|
scc_ir_module_t *ir_module) {
|
||||||
ctx->gpr_caller_saved = 0;
|
ctx->frame_alloc = nullptr;
|
||||||
ctx->gpr_callee_saved = 0;
|
|
||||||
ctx->ir_module = ir_module;
|
ctx->ir_module = ir_module;
|
||||||
ctx->reg_alloc_func = func;
|
scc_hashtable_init(&ctx->node2loc, hash_func, equal_func);
|
||||||
|
scc_vec_init(ctx->loc_vec);
|
||||||
ctx->alloc_stack_size = 0;
|
ctx->reg_alloc_func = strategy;
|
||||||
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_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
|
#define add_loc(ctx, loc, val_ref) \
|
||||||
scc_ir_func_t *func) {
|
do { \
|
||||||
ctx->alloc_stack_size = ctx->init_stack_size;
|
scc_vec_push(ctx->loc_vec, loc); \
|
||||||
scc_hashtable_drop(&ctx->node_ref2reg_loc);
|
scc_hashtable_set(&ctx->node2loc, (void *)(usize)val_ref, \
|
||||||
scc_vec_free(ctx->reg_loc_vec);
|
(void *)(usize)(scc_vec_size(ctx->loc_vec))); \
|
||||||
scc_vec_init(ctx->reg_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_reg_loc_t loc;
|
||||||
|
|
||||||
|
// 为参数分配槽位(参数通过寄存器传入,但需要保存到栈上)
|
||||||
scc_vec_foreach(func->params, i) {
|
scc_vec_foreach(func->params, i) {
|
||||||
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
scc_ir_value_ref_t node_ref = scc_vec_at(func->params, i);
|
||||||
loc.kind = SCC_REG_KIND_FUNC_ARG;
|
loc.kind = SCC_REG_KIND_STACK_ADDR;
|
||||||
loc.idx = i;
|
loc.data.slot_idx =
|
||||||
ctx->alloc_stack_size += 8;
|
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0); // 参数按8字节
|
||||||
scc_hashtable_set(&ctx->node_ref2reg_loc, (void *)(usize)node_ref,
|
add_loc(ctx, loc, node_ref);
|
||||||
(void *)scc_vec_size(ctx->reg_loc_vec));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
// 遍历所有指令,为需要存储结果的节点分配槽位
|
||||||
scc_vec_foreach(func->bblocks, i) {
|
scc_vec_foreach(func->bblocks, i) {
|
||||||
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
||||||
scc_ir_bblock_t *bblock =
|
scc_ir_bblock_t *bblock =
|
||||||
scc_ir_module_get_bblock(ctx->ir_module, bblock_ref);
|
scc_ir_module_get_bblock(ctx->ir_module, bblock_ref);
|
||||||
Assert(bblock != nullptr);
|
|
||||||
scc_vec_foreach(bblock->instrs, j) {
|
scc_vec_foreach(bblock->instrs, j) {
|
||||||
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, j);
|
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, j);
|
||||||
scc_ir_value_t *node =
|
scc_ir_value_t *node =
|
||||||
scc_ir_module_get_value(ctx->ir_module, node_ref);
|
scc_ir_module_get_value(ctx->ir_module, node_ref);
|
||||||
Assert(node != nullptr);
|
if (node == nullptr)
|
||||||
loc.kind = SCC_REG_KIND_UNDEF;
|
continue;
|
||||||
switch (node->tag) {
|
switch (node->tag) {
|
||||||
case SCC_IR_VALUE_TAG_LOAD:
|
case SCC_IR_VALUE_TAG_LOAD:
|
||||||
case SCC_IR_VALUE_TAG_OP:
|
case SCC_IR_VALUE_TAG_OP:
|
||||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
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.kind = SCC_REG_KIND_STACK;
|
||||||
loc.idx = ctx->alloc_stack_size;
|
loc.data.slot_idx =
|
||||||
|
frame_alloc->alloc_spill_slot(frame_alloc, 8, 0);
|
||||||
ctx->alloc_stack_size += 8;
|
add_loc(ctx, loc, node_ref);
|
||||||
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;
|
break;
|
||||||
}
|
|
||||||
case SCC_IR_VALUE_TAG_ALLOC: {
|
case SCC_IR_VALUE_TAG_ALLOC: {
|
||||||
// 为 alloc 分配栈偏移,但不作为普通值存储
|
|
||||||
loc.kind =
|
|
||||||
SCC_REG_KIND_STACK_ADDR; // 实际不需要存储到 reg_loc_vec
|
|
||||||
scc_ir_type_t *type =
|
scc_ir_type_t *type =
|
||||||
scc_ir_module_get_type(ctx->ir_module, node->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);
|
Assert(type->tag == SCC_IR_TYPE_PTR);
|
||||||
int len = scc_ir2mcode_type_width(
|
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||||
ctx->ir_module,
|
ctx->ir_module, type->data.pointer.base);
|
||||||
scc_ir_module_get_type(ctx->ir_module,
|
int size = scc_ir2mcode_type_width(ctx->ir_module, base_type);
|
||||||
type->data.pointer.base));
|
|
||||||
len = len % 8 == 0 ? len : len + 8 - len % 8;
|
|
||||||
ctx->alloc_stack_size += len;
|
|
||||||
|
|
||||||
// 记录偏移
|
loc.kind = SCC_REG_KIND_STACK_ADDR;
|
||||||
scc_vec_push(ctx->reg_loc_vec, loc);
|
loc.data.slot_idx = frame_alloc->alloc_local_slot(
|
||||||
scc_hashtable_set(&ctx->node_ref2reg_loc,
|
frame_alloc, size, 0, node->name);
|
||||||
(void *)(usize)node_ref,
|
add_loc(ctx, loc, 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));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -108,5 +76,4 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &ctx->node_ref2reg_loc;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
if (reloc->reloc_type == SCCF_RELOC_TYPE_EMPTY) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Assert(reloc->sect_type == SCCF_SECT_CODE);
|
||||||
sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx);
|
sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx);
|
||||||
const char *name = &scc_vec_at(strtab, sym->name_offset);
|
const char *name = &scc_vec_at(strtab, sym->name_offset);
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
#define SCC_STR(str) _SCC_STR(str)
|
#define SCC_STR(str) _SCC_STR(str)
|
||||||
|
|
||||||
#define SCC_ARRLEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
#define SCC_ARRLEN(arr) (sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
#define SCC_FUNC
|
#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_min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define scc_max(a, b) ((a) > (b) ? (a) : (b))
|
#define scc_max(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|||||||
Reference in New Issue
Block a user