#include #include #include #include #include #define GET_MODULE(ctx) (&(ctx->cprog->module)) static bool scc_type_is_signed(scc_ir_type_t *type) { return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 || type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64); } 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 *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 (value->tag) { case SCC_IR_VALUE_TAG_CONST_INT: scc_ir_type_t *type = scc_ir_module_get_type(GET_MODULE(ctx), value->type); Assert(type != 0); 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: TODO(); break; case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: TODO(); break; case SCC_IR_VALUE_TAG_FUNC_ARG_REF: case SCC_IR_VALUE_TAG_ALLOC: default: idx = (usize)scc_hashtable_get(ctx->noderef2regloc, (void *)(usize)node_ref); break; } 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_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->data.gpr_idx != reg) { scc_mcode_amd64_mov_r64_r64(mcode, reg, loc->data.gpr_idx); } else { TODO(); } break; case SCC_REG_KIND_STACK: 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: // 将栈地址加载到寄存器(取地址) 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_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->data.gpr_idx != reg) { scc_mcode_amd64_mov_r64_r64(mcode, loc->data.gpr_idx, reg); } break; case SCC_REG_KIND_STACK: 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; default: Panic("unsupported location %d", loc->kind); break; } } // 临时存储待修补条目 typedef struct patch { usize pos; usize target_bb_ref; } patch_t; 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 *value = scc_ir_module_get_value(GET_MODULE(ctx), node_ref); if (value == nullptr) { LOG_ERROR("invalid value ref"); return; } 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 value type: %d", value->tag); break; ///< 函数参数引用 case SCC_IR_VALUE_TAG_FUNC_ARG_REF: ///< ABI break; case SCC_IR_VALUE_TAG_BLOCK_ARG_REF: ///< 基本块参数引用 break; case SCC_IR_VALUE_TAG_ALLOC: ///< 分配内存(stack) case SCC_IR_VALUE_TAG_GLOBAL_ALLOC: ///< 全局分配(bss break; ///< 加载数据 case SCC_IR_VALUE_TAG_LOAD: { // value->data.load.target scc_reg_loc_t from; scc_reg_loc_t to; parse_location(ctx, &from, value->data.load.target); parse_location(ctx, &to, node_ref); 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), 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); bool is_signed = scc_type_is_signed(base_type); // 间接加载到 RAX if (width == 1) { if (is_signed) scc_mcode_amd64_movsx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); else scc_mcode_amd64_movzx_r64_m8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); } else if (width == 2) { if (is_signed) scc_mcode_amd64_movsx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); else scc_mcode_amd64_movzx_r64_m16(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); } else if (width == 4) { if (is_signed) scc_mcode_amd64_movsx_r64_m32(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); else scc_mcode_amd64_mov_r32_m32( &ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); // 32位加载自动清零高位 } else if (width == 8) { // 8 scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); } else { LOG_WARN("unsupported type width: %d", width); scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); } // 存储结果 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, value->data.store.value); parse_location(ctx, &addr_loc, value->data.store.target); // 将值加载到 RAX load_value_to_reg(ctx, &val_loc, SCC_AMD64_RAX); // 将目标地址加载到 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), 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); // 根据宽度生成存储指令 if (width == 1) { scc_mcode_amd64_mov_m8_r8(&ctx->sect_mcode, SCC_AMD64_RCX, SCC_AMD64_RAX); } else if (width == 2) { scc_mcode_amd64_mov_m16_r16(&ctx->sect_mcode, SCC_AMD64_RCX, SCC_AMD64_RAX); } else if (width == 4) { scc_mcode_amd64_mov_m32_r32(&ctx->sect_mcode, SCC_AMD64_RCX, SCC_AMD64_RAX); } else { // width == 8 scc_mcode_amd64_mov_m64_r64(&ctx->sect_mcode, SCC_AMD64_RCX, SCC_AMD64_RAX); } break; } ///< 获取指针 case SCC_IR_VALUE_TAG_GET_ELEM_PTR: { scc_reg_loc_t loc_res; parse_location(ctx, &loc_res, node_ref); scc_ir_value_t *src_addr = scc_ir_module_get_value( GET_MODULE(ctx), value->data.get_elem_ptr.src_addr); Assert(src_addr != nullptr); if (value->data.get_elem_ptr.index == 0) { if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) { // 全局变量:RIP相对寻址 scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, SCC_AMD64_RAX, 0); usize sym_idx = sccf_builder_get_symbol_idx(ctx->builder, src_addr->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->sect_mcode.mcode) - 4, .addend = 4, .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, value->data.get_elem_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, value->data.get_elem_ptr.src_addr); load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); } } else { // TODO parse_value(ctx, value->data.get_elem_ptr.index, patches); scc_reg_loc_t src_loc; scc_reg_loc_t idx_loc; parse_location(ctx, &src_loc, value->data.get_elem_ptr.src_addr); parse_location(ctx, &idx_loc, value->data.get_elem_ptr.index); src_loc.kind = SCC_REG_KIND_STACK_ADDR; load_value_to_reg(ctx, &src_loc, SCC_AMD64_RAX); load_value_to_reg(ctx, &idx_loc, SCC_AMD64_RDX); scc_mcode_amd64_lea_r64_m64_sib(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX, SCC_AMD64_RDX, 1, 0); } store_value_from_reg(ctx, &loc_res, SCC_AMD64_RAX); break; } ///< 二元运算 case SCC_IR_VALUE_TAG_OP: { scc_reg_loc_t loc_lhs; parse_location(ctx, &loc_lhs, value->data.op.lhs); scc_reg_loc_t loc_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, &loc_lhs, SCC_AMD64_RAX); // 将右操作数加载到 RCX 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; case SCC_IR_OP_ADD: scc_mcode_amd64_add_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); break; case SCC_IR_OP_SUB: scc_mcode_amd64_sub_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); break; case SCC_IR_OP_MUL: scc_mcode_amd64_mul_r64(&ctx->sect_mcode, SCC_AMD64_RCX); break; case SCC_IR_OP_DIV: case SCC_IR_OP_MOD: TODO(); break; case SCC_IR_OP_AND: scc_mcode_amd64_and_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); break; case SCC_IR_OP_OR: scc_mcode_amd64_or_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); break; case SCC_IR_OP_XOR: scc_mcode_amd64_xor_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); break; case SCC_IR_OP_NOT: scc_mcode_amd64_not_r64(&ctx->sect_mcode, SCC_AMD64_RAX); break; case SCC_IR_OP_SHL: case SCC_IR_OP_SHR: case SCC_IR_OP_SAR: TODO(); break; case SCC_IR_OP_NEQ: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_NE, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; case SCC_IR_OP_EQ: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_E, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; case SCC_IR_OP_GT: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_G, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; case SCC_IR_OP_LT: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_L, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; case SCC_IR_OP_GE: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_GE, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; case SCC_IR_OP_LE: scc_mcode_amd64_cmp_r64_r64(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RCX); scc_mcode_amd64_setcc_r8(&ctx->sect_mcode, SCC_AMD64_COND_LE, SCC_AMD64_RAX); scc_mcode_amd64_movzx_r64_r8(&ctx->sect_mcode, SCC_AMD64_RAX, SCC_AMD64_RAX); break; default: LOG_FATAL("unknown op: %d", value->data.op.op); break; } // 将 RAX 中的结果存储到 res 位置 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, value->data.branch.cond); // (void)loc; 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)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)value->data.branch.false_bblock}; scc_vec_push(*patches, patch_false); break; } ///< 无条件跳转 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)value->data.jump.target_bblock}; scc_vec_push(*patches, patch); break; } ///< 调用函数 case SCC_IR_VALUE_TAG_CALL: { scc_reg_loc_t loc; /* ABI RAX 不稳定的 返回值寄存器 RCX 不稳定的 第一个整型自变量 RDX 不稳定的 第二个整型自变量 R8 不稳定的 第三个整型自变量 R9 不稳定的 第四个整型自变量 */ 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, &loc, SCC_AMD64_RCX); } else if (i == 1) { load_value_to_reg(ctx, &loc, SCC_AMD64_RDX); } else if (i == 2) { load_value_to_reg(ctx, &loc, SCC_AMD64_R8); } else if (i == 3) { load_value_to_reg(ctx, &loc, SCC_AMD64_R9); } else { LOG_FATAL("not support more than 4 args"); } // scc_mcode_amd64_push_r64(); } scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee); if (!func) { LOG_ERROR("invalid function reference"); return; } // FIXME hack func value if (scc_vec_size(func->bblocks)) { scc_mcode_amd64_call_rel32(&ctx->sect_mcode, 0); } else { scc_mcode_amd64_call_mem_rip_rel32(&ctx->sect_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->sect_mcode.mcode) - 4, .addend = 4, .sect_type = SCCF_SECT_CODE, .sym_idx = sym_idx, }); // 处理返回值 scc_ir_type_t *func_type = scc_ir_module_get_type(GET_MODULE(ctx), func->type); Assert(func_type); scc_ir_type_t *ret_type = scc_ir_module_get_type( 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, &loc, SCC_AMD64_RAX); } break; } ///< 函数返回 case SCC_IR_VALUE_TAG_RET: { if (value->data.ret.ret_val) { scc_reg_loc_t loc; 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); scc_mcode_amd64_ret(&ctx->sect_mcode); break; } default: LOG_FATAL("unknown value type: %d", value->tag); UNREACHABLE(); break; } } static void parse_bblock(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_t *bblock, patch_vec_t *patches) { // 打印基本块中的每条指令 for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) { scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, i); parse_value(ctx, node_ref, patches); } } static u32 hash_func(const void *key) { return (u32)(usize)key; } 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 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)); // 建立 bblock_ref -> id 的映射 scc_hashtable_t ref2id; scc_hashtable_init(&ref2id, hash_func, equal_func); for (usize i = 0; i < bblock_cnt; i++) { scc_ir_bblock_ref_t ref = scc_vec_at(func->bblocks, i); scc_hashtable_set(&ref2id, (void *)(usize)ref, (void *)i); } patch_vec_t patches; scc_vec_init(patches); scc_mcode_amd64_push_r64(&ctx->sect_mcode, SCC_AMD64_RBP); scc_mcode_amd64_sub_rsp_imm32(&ctx->sect_mcode, ctx->stack_size); scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RBP, SCC_AMD64_RSP, ctx->stack_size); scc_reg_loc_t loc; scc_vec_foreach(func->params, i) { // scc_ir_value_t *param = // scc_ir_module_get_value(GET_MODULE(ctx), ); 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, &loc, SCC_AMD64_RCX); } else if (i == 1) { store_value_from_reg(ctx, &loc, SCC_AMD64_RDX); } else if (i == 2) { store_value_from_reg(ctx, &loc, SCC_AMD64_R8); } else if (i == 3) { store_value_from_reg(ctx, &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); scc_ir_bblock_t *bblock = scc_ir_module_get_bblock(GET_MODULE(ctx), bblock_ref); if (bblock == nullptr) { LOG_FATAL("\n"); return; } bblock_offsets[i] = scc_vec_size(ctx->sect_mcode.mcode); parse_bblock(ctx, bblock, &patches); } // 回填所有跳转偏移 u8 *buf = scc_vec_unsafe_get_data(ctx->sect_mcode.mcode); scc_vec_foreach(patches, idx) { patch_t *p = &scc_vec_at(patches, idx); usize target_id = (usize)scc_hashtable_get(&ref2id, (void *)(usize)p->target_bb_ref); 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; } scc_free(bblock_offsets); scc_vec_free(patches); scc_hashtable_drop(&ref2id); } void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) { scc_reg_alloc_init(&ctx->reg_alloc, scc_reg_alloc_strategy_pure_stack, GET_MODULE(ctx)); 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)); Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC); scc_ir_value_t *value = scc_ir_module_get_value( GET_MODULE(ctx), galloc->data.global_alloc.value); Assert(value != nullptr); sccf_sym_t sym = (sccf_sym_t){ .sccf_sect_offset = scc_vec_size(ctx->sect_data), .sccf_sect_type = SCCF_SECT_DATA, .sccf_sym_bind = galloc->name ? SCCF_SYM_BIND_GLOBAL : SCCF_SYM_BIND_LOCAL, .sccf_sym_size = 4, // FIXME on windows using rel32, on linux using ? .sccf_sym_type = SCCF_SYM_TYPE_DATA, .sccf_sym_vis = SCCF_SYM_VIS_DEFAULT, }; scc_vec_foreach(value->data.const_array.fields, j) { scc_vec_push(ctx->sect_data, scc_vec_at(value->data.const_array.fields, j)); } usize sym_idx = sccf_builder_add_symbol(ctx->builder, galloc->name, &sym); Assert(sym_idx != 0); } scc_vec_foreach(ctx->cprog->func_decls, i) { scc_ir_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_decls, i); scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(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_value_ref_t func_ref = scc_vec_at(ctx->cprog->func_defs, i); scc_ir_func_t *func = scc_ir_module_get_func(GET_MODULE(ctx), func_ref); if (!func) { LOG_ERROR("invalid function reference"); return; } sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(ctx->builder, func->name); Assert(sym != nullptr); sym->sccf_sect_offset = scc_vec_size(ctx->sect_mcode.mcode); parse_function(ctx, func); } u8 *buf = scc_vec_unsafe_get_data(ctx->sect_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); if (sym->sccf_sect_type == SCCF_SECT_CODE && 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; } } } sccf_sect_data_t text_section; scc_vec_unsafe_from_buffer(text_section, scc_vec_unsafe_get_data(ctx->sect_mcode.mcode), scc_vec_size(ctx->sect_mcode.mcode)); sccf_builder_add_text_section(ctx->builder, &text_section); sccf_builder_add_data_section(ctx->builder, &ctx->sect_data); // FIXME maybe _entry and add crt ctx->builder->entry_symbol_name = "main"; }