|
|
|
|
@@ -4,7 +4,7 @@
|
|
|
|
|
#include <scc_ir2mcode.h>
|
|
|
|
|
|
|
|
|
|
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
|
|
|
|
scc_ir_bblock_ref_t node_ref) {
|
|
|
|
|
scc_ir_node_ref_t node_ref) {
|
|
|
|
|
Assert(ctx != null && loc != null);
|
|
|
|
|
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
|
|
|
|
|
if (node == null) {
|
|
|
|
|
@@ -27,6 +27,17 @@ static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
|
|
|
|
case SCC_IR_NODE_CONST_FLOAT:
|
|
|
|
|
TODO();
|
|
|
|
|
break;
|
|
|
|
|
case SCC_IR_NODE_FUNC_ARG_REF: {
|
|
|
|
|
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_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;
|
|
|
|
|
arg_loc.idx = 8 * node->data.arg_ref.idx;
|
|
|
|
|
*loc = arg_loc;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
idx = (usize)scc_hashtable_get(ctx->noderef2regloc,
|
|
|
|
|
(void *)(usize)node_ref);
|
|
|
|
|
@@ -47,8 +58,9 @@ static void load_value_to_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc, int reg) {
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SCC_REG_KIND_STACK:
|
|
|
|
|
// FIXME -8 for rdp
|
|
|
|
|
scc_mcode_amd64_mov_r64_m64_disp32(mcode, reg, SCC_AMD64_RBP,
|
|
|
|
|
-loc->idx);
|
|
|
|
|
-loc->idx - 8);
|
|
|
|
|
break;
|
|
|
|
|
case SCC_REG_KIND_IMM:
|
|
|
|
|
scc_mcode_amd64_mov_r64_imm64(mcode, reg, loc->idx); // 或 imm32
|
|
|
|
|
@@ -67,7 +79,8 @@ static void store_value_from_reg(scc_mcode_t *mcode, scc_reg_loc_t *loc,
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case SCC_REG_KIND_STACK:
|
|
|
|
|
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx,
|
|
|
|
|
// FIXME -8 for rdp
|
|
|
|
|
scc_mcode_amd64_mov_m64_disp32_r64(mcode, SCC_AMD64_RBP, -loc->idx - 8,
|
|
|
|
|
reg);
|
|
|
|
|
break;
|
|
|
|
|
case SCC_REG_KIND_IMM:
|
|
|
|
|
@@ -95,13 +108,16 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (node->tag) {
|
|
|
|
|
case SCC_IR_NODE_CONV: ///< 类型转换
|
|
|
|
|
case SCC_IR_NODE_FUNC_ARG_REF: ///< 函数参数引用
|
|
|
|
|
case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用
|
|
|
|
|
case SCC_IR_NODE_CONV: ///< 类型转换
|
|
|
|
|
LOG_FATAL("Unsupported node type: %d", node->tag);
|
|
|
|
|
break;
|
|
|
|
|
case SCC_IR_NODE_ALLOC: ///< 分配内存(stack)
|
|
|
|
|
case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss)
|
|
|
|
|
///< 函数参数引用
|
|
|
|
|
case SCC_IR_NODE_FUNC_ARG_REF:
|
|
|
|
|
///< ABI
|
|
|
|
|
break;
|
|
|
|
|
case SCC_IR_NODE_BLOCK_ARG_REF: ///< 基本块参数引用
|
|
|
|
|
case SCC_IR_NODE_ALLOC: ///< 分配内存(stack)
|
|
|
|
|
case SCC_IR_NODE_GLOBAL_ALLOC: ///< 全局分配(bss)
|
|
|
|
|
break;
|
|
|
|
|
case SCC_IR_NODE_LOAD: ///< 加载数据
|
|
|
|
|
{
|
|
|
|
|
@@ -127,7 +143,8 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
case SCC_IR_NODE_GET_PTR: ///< 获取指针
|
|
|
|
|
case SCC_IR_NODE_GET_ELEM_PTR: ///< 获取元素指针(used by array)
|
|
|
|
|
TODO();
|
|
|
|
|
case SCC_IR_NODE_OP: ///< 二元运算
|
|
|
|
|
///< 二元运算
|
|
|
|
|
case SCC_IR_NODE_OP: {
|
|
|
|
|
scc_reg_loc_t loc_lhs;
|
|
|
|
|
parse_location(ctx, &loc_lhs, node->data.op.lhs);
|
|
|
|
|
scc_reg_loc_t loc_rhs;
|
|
|
|
|
@@ -216,6 +233,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
// 将 RAX 中的结果存储到 res 位置
|
|
|
|
|
store_value_from_reg(&ctx->mcode, &loc_res, SCC_AMD64_RAX);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
///< 有条件分支
|
|
|
|
|
case SCC_IR_NODE_BRANCH: {
|
|
|
|
|
scc_reg_loc_t loc;
|
|
|
|
|
@@ -257,7 +275,7 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
R9 不稳定的 第四个整型自变量
|
|
|
|
|
*/
|
|
|
|
|
scc_vec_foreach(node->data.call.args, i) {
|
|
|
|
|
parse_location(ctx, &loc, node->data.branch.cond);
|
|
|
|
|
parse_location(ctx, &loc, scc_vec_at(node->data.call.args, i));
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RCX);
|
|
|
|
|
} else if (i == 1) {
|
|
|
|
|
@@ -280,9 +298,22 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scc_mcode_amd64_call_rel32(&ctx->mcode, 0);
|
|
|
|
|
usize sym_idx = sccf_builder_get_symbol_idx(&ctx->builder, func->name);
|
|
|
|
|
Assert(sym_idx != 0);
|
|
|
|
|
sccf_builder_add_reloc(&ctx->builder,
|
|
|
|
|
(sccf_reloc_t){
|
|
|
|
|
.reloc_type = SCCF_RELOC_TYPE_REL,
|
|
|
|
|
.offset = scc_vec_size(ctx->mcode.mcode) - 4,
|
|
|
|
|
.addend = 4,
|
|
|
|
|
.sect_type = SCCF_SECT_CODE,
|
|
|
|
|
.sym_idx = sym_idx,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 处理返回值
|
|
|
|
|
scc_ir_type_t *ret_type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
|
|
|
|
|
scc_ir_type_t *func_type = scc_ir_ctx_get_type(ctx->ir_ctx, func->type);
|
|
|
|
|
Assert(func_type);
|
|
|
|
|
scc_ir_type_t *ret_type =
|
|
|
|
|
scc_ir_ctx_get_type(ctx->ir_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->mcode, &loc, SCC_AMD64_RAX);
|
|
|
|
|
@@ -296,12 +327,13 @@ static void parse_node(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
|
|
|
|
parse_location(ctx, &loc, node->data.ret.ret_val);
|
|
|
|
|
load_value_to_reg(&ctx->mcode, &loc, SCC_AMD64_RAX);
|
|
|
|
|
}
|
|
|
|
|
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RSP, SCC_AMD64_RBP);
|
|
|
|
|
scc_mcode_amd64_add_rsp_imm32(&ctx->mcode, ctx->stack_size);
|
|
|
|
|
scc_mcode_amd64_pop_r64(&ctx->mcode, SCC_AMD64_RBP);
|
|
|
|
|
scc_mcode_amd64_ret(&ctx->mcode);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
LOG_FATAL("unknown node type: %d", node->tag);
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -325,7 +357,9 @@ static int equal_func(const void *key1, const void *key2) {
|
|
|
|
|
static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
|
|
|
|
ctx->noderef2regloc = scc_reg_alloc(&ctx->reg_alloc, func);
|
|
|
|
|
// 对齐到 16 字节
|
|
|
|
|
usize stack_size = (ctx->reg_alloc.alloc_stack_size + 15) & ~15;
|
|
|
|
|
// FIXME
|
|
|
|
|
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_offsets = scc_calloc(bblock_cnt, sizeof(usize));
|
|
|
|
|
@@ -341,8 +375,28 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
|
|
|
|
scc_vec_init(patches);
|
|
|
|
|
|
|
|
|
|
scc_mcode_amd64_push_r64(&ctx->mcode, SCC_AMD64_RBP);
|
|
|
|
|
scc_mcode_amd64_mov_r64_r64(&ctx->mcode, SCC_AMD64_RBP, SCC_AMD64_RSP);
|
|
|
|
|
scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, stack_size);
|
|
|
|
|
scc_mcode_amd64_sub_rsp_imm32(&ctx->mcode, ctx->stack_size);
|
|
|
|
|
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->mcode, SCC_AMD64_RBP,
|
|
|
|
|
SCC_AMD64_RSP, ctx->stack_size);
|
|
|
|
|
scc_reg_loc_t loc;
|
|
|
|
|
scc_vec_foreach(func->params, i) {
|
|
|
|
|
// scc_ir_node_t *param =
|
|
|
|
|
// scc_ir_ctx_get_node(ctx->ir_ctx, );
|
|
|
|
|
scc_ir_node_ref_t node_ref = scc_vec_at(func->params, i);
|
|
|
|
|
parse_location(ctx, &loc, node_ref);
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RCX);
|
|
|
|
|
} else if (i == 1) {
|
|
|
|
|
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_RDX);
|
|
|
|
|
} else if (i == 2) {
|
|
|
|
|
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R8);
|
|
|
|
|
} else if (i == 3) {
|
|
|
|
|
store_value_from_reg(&ctx->mcode, &loc, SCC_AMD64_R9);
|
|
|
|
|
} else {
|
|
|
|
|
LOG_FATAL("not support more than 4 args");
|
|
|
|
|
}
|
|
|
|
|
// scc_mcode_amd64_push_r64();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
|
|
|
|
|
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
|
|
|
|
@@ -367,12 +421,8 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
|
|
|
|
usize target_off = bblock_offsets[target_id];
|
|
|
|
|
usize next_off = p->pos;
|
|
|
|
|
i32 rel = (i32)(target_off - next_off);
|
|
|
|
|
// 写入到指令的偏移字段(小端)
|
|
|
|
|
// FIXME 写入到指令的偏移字段(小端)
|
|
|
|
|
*(u32 *)(&buf[p->pos - 4]) = rel;
|
|
|
|
|
// buf[p->pos + 1] = (u8)(rel >> 0);
|
|
|
|
|
// buf[p->pos + 2] = (u8)(rel >> 8);
|
|
|
|
|
// buf[p->pos + 3] = (u8)(rel >> 16);
|
|
|
|
|
// buf[p->pos + 4] = (u8)(rel >> 24);
|
|
|
|
|
}
|
|
|
|
|
scc_free(bblock_offsets);
|
|
|
|
|
scc_vec_free(patches);
|
|
|
|
|
@@ -382,6 +432,39 @@ 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, ctx->ir_ctx);
|
|
|
|
|
|
|
|
|
|
scc_vec_foreach(ctx->cprog->func_decls, i) {
|
|
|
|
|
scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i);
|
|
|
|
|
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
|
|
|
|
|
if (!func) {
|
|
|
|
|
LOG_ERROR("invalid function reference");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sccf_sym_t sym = {0};
|
|
|
|
|
if (scc_vec_size(func->bblocks)) {
|
|
|
|
|
sym = (sccf_sym_t){
|
|
|
|
|
.sccf_sect_offset = 0,
|
|
|
|
|
.sccf_sect_type = SCCF_SECT_CODE,
|
|
|
|
|
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
|
|
|
|
|
.sccf_sym_size = 0,
|
|
|
|
|
.sccf_sym_type = SCCF_SYM_TYPE_FUNC,
|
|
|
|
|
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
sym = (sccf_sym_t){
|
|
|
|
|
.sccf_sect_offset = 0,
|
|
|
|
|
.sccf_sect_type = SCCF_SECT_NONE,
|
|
|
|
|
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
|
|
|
|
|
.sccf_sym_size = 0,
|
|
|
|
|
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
|
|
|
|
|
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
usize sym_idx =
|
|
|
|
|
sccf_builder_add_symbol(&ctx->builder, func->name, &sym);
|
|
|
|
|
Assert(sym_idx != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scc_vec_foreach(ctx->cprog->func_defs, i) {
|
|
|
|
|
scc_ir_node_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i);
|
|
|
|
|
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
|
|
|
|
|
@@ -389,16 +472,10 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
|
|
|
|
LOG_ERROR("invalid function reference");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sccf_sym_t sym = {
|
|
|
|
|
.sccf_sect_offset = scc_vec_size(ctx->mcode.mcode),
|
|
|
|
|
.sccf_sect_type = SCCF_SECT_CODE,
|
|
|
|
|
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
|
|
|
|
|
.sccf_sym_size = 0,
|
|
|
|
|
.sccf_sym_type = SCCF_SYM_TYPE_FUNC,
|
|
|
|
|
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
|
|
|
|
|
};
|
|
|
|
|
sccf_builder_add_symbol(&ctx->builder, func->name, &sym);
|
|
|
|
|
|
|
|
|
|
sccf_sym_t *sym =
|
|
|
|
|
sccf_builder_get_symbol_unsafe(&ctx->builder, func->name);
|
|
|
|
|
Assert(sym != null);
|
|
|
|
|
sym->sccf_sect_offset = scc_vec_size(ctx->mcode.mcode);
|
|
|
|
|
parse_function(ctx, func);
|
|
|
|
|
}
|
|
|
|
|
sccf_sect_data_t text_section;
|
|
|
|
|
@@ -409,4 +486,28 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
|
|
|
|
sccf_sect_data_t data_section;
|
|
|
|
|
scc_vec_init(data_section);
|
|
|
|
|
sccf_builder_add_data_section(&ctx->builder, &data_section);
|
|
|
|
|
|
|
|
|
|
u8 *buf = scc_vec_unsafe_get_data(ctx->mcode.mcode);
|
|
|
|
|
scc_vec_foreach(ctx->builder.relocs, i) {
|
|
|
|
|
sccf_reloc_t *reloc = &scc_vec_at(ctx->builder.relocs, i);
|
|
|
|
|
if (reloc->sym_idx == 0) {
|
|
|
|
|
Panic("relocate to an invalid symbol");
|
|
|
|
|
}
|
|
|
|
|
sccf_sym_t *sym = &scc_vec_at(ctx->builder.symtab, reloc->sym_idx);
|
|
|
|
|
if (sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN) {
|
|
|
|
|
Assert(reloc->reloc_type == SCCF_RELOC_TYPE_REL);
|
|
|
|
|
|
|
|
|
|
Assert(sym->sccf_sect_type == SCCF_SECT_CODE);
|
|
|
|
|
Assert(sym->sccf_sym_type == SCCF_SYM_TYPE_FUNC);
|
|
|
|
|
i64 target_off = sym->sccf_sect_offset;
|
|
|
|
|
i64 next_off = reloc->offset + reloc->addend;
|
|
|
|
|
i32 rel = (i32)(target_off - next_off);
|
|
|
|
|
// FIXME 写入到指令的偏移字段(小端)
|
|
|
|
|
*(i32 *)(&buf[reloc->offset]) = rel;
|
|
|
|
|
|
|
|
|
|
reloc->reloc_type = SCCF_RELOC_TYPE_EMPTY;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// FIXME
|
|
|
|
|
ctx->builder.entry_symbol_name = "main";
|
|
|
|
|
}
|
|
|
|
|
|