fix: multi-return-value error, return in rax/rdi/rsi/rdx to decrease the binary code...
authoryu.dongliang <18588496441@163.com>
Sun, 13 Oct 2024 13:17:09 +0000 (21:17 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 13 Oct 2024 13:17:14 +0000 (21:17 +0800)
native/x64/scf_x64_inst.c
native/x64/scf_x64_peephole.c
native/x64/scf_x64_reg.c
native/x64/scf_x64_reg.h

index 951ef23312c53f5d8046160b928850e98d218860..7f6a32e601eff46ffa1fa2dc3c26af266075dab8 100644 (file)
@@ -409,6 +409,21 @@ static int _x64_call_update_dsts(scf_3ac_code_t* c, scf_function_t* f, scf_regis
                } else {
                        scf_rela_t* rela = NULL;
 
+                       if (0 == v->bp_offset && !v->global_flag && !v->local_flag) {
+
+                               int size = f->local_vars_size + dst_size;
+
+                               if (size & 0x7)
+                                       size = (size + 7) >> 3 << 3;
+
+                               v->bp_offset = -size;
+                               v->tmp_flag  = 1;
+
+                               f->local_vars_size = size;
+
+                               scf_logd("v->bp_offset: %d, local_flag: %d, tmp_flag: %d, rs->name: %s\n", v->bp_offset, v->local_flag, v->tmp_flag, rs->name);
+                       }
+
                        inst = x64_make_inst_G2M(&rela, mov, dn->var, NULL, rs);
                        X64_INST_ADD_CHECK(c->instructions, inst);
                        X64_RELA_ADD_CHECK(f->data_relas, rela, c, dn->var, NULL);
@@ -1414,10 +1429,10 @@ static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
        scf_variable_t*     v    = NULL;
        scf_rela_t*         rela = NULL;
 
-       scf_register_t* rd   = NULL;
-       scf_register_t* rs   = NULL;
-       scf_register_t* rsp  = x64_find_register("rsp");
-       scf_register_t* rbp  = x64_find_register("rbp");
+       scf_register_t*     rd   = NULL;
+       scf_register_t*     rs   = NULL;
+       scf_register_t*     rsp  = x64_find_register("rsp");
+       scf_register_t*     rbp  = x64_find_register("rbp");
 
        scf_x64_OpCode_t*   pop;
        scf_x64_OpCode_t*   mov;
@@ -1445,6 +1460,11 @@ static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
                int retsize = size > 4 ? 8 : 4;
 
+               if (src->dag_node->color > 0)
+                       rs = x64_find_register_color_bytes(src->dag_node->color, size);
+               else
+                       rs = NULL;
+
                if (is_float) {
                        rd = x64_find_register_type_id_bytes(is_float, 0, retsize);
 
@@ -1457,20 +1477,9 @@ static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                                mov = x64_find_OpCode(SCF_X64_MOVSS, size, rd->bytes, SCF_X64_E2G);
                        else
                                mov = x64_find_OpCode(SCF_X64_MOVSD, size, rd->bytes, SCF_X64_E2G);
-
                } else {
                        rd = x64_find_register_type_id_bytes(is_float, x64_abi_ret_regs[i], retsize);
 
-                       if (0 == src->dag_node->color) {
-                               if (rd->bytes > size)
-                                       scf_variable_extend_bytes(v, rd->bytes);
-
-                               mov  = x64_find_OpCode(SCF_X64_MOV, rd->bytes, rd->bytes, SCF_X64_I2G);
-                               inst = x64_make_inst_I2G(mov, rd, (uint8_t*)&v->data, rd->bytes);
-                               X64_INST_ADD_CHECK(c->instructions, inst);
-                               continue;
-                       }
-
                        if (rd->bytes > size) {
                                if (scf_variable_signed(v))
                                        mov = x64_find_OpCode(SCF_X64_MOVSX, size, rd->bytes, SCF_X64_E2G);
@@ -1482,38 +1491,48 @@ static int _x64_inst_return_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 
                scf_logd("rd: %s, rd->dag_nodes->size: %d\n", rd->name, rd->dag_nodes->size);
 
-               if (src->dag_node->color > 0) {
-
-                       int start = c->instructions->size;
+               int ret = x64_save_reg(rd, c, f);
+               if (ret < 0)
+                       return ret;
 
-                       X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
+               if (src->dag_node->color > 0) {
+                       int j;
+                       for (j = 0; j < i; j++) {
+                               if (x64_abi_ret_regs[j] == rs->id)
+                                       break;
+                       }
 
-                       if (!X64_COLOR_CONFLICT(rd->color, rs->color)) {
+                       if (j < i) {
+                               scf_vector_del(rs->dag_nodes, src->dag_node);
 
-                               int ret = x64_save_reg(rd, c, f);
-                               if (ret < 0)
-                                       return ret;
+                               scf_logd("i: %d, j: %d, rd: %s, rs: %s, rs->dag_node->size: %d\n", i, j, rd->name, rs->name, rs->dag_nodes->size);
 
-                               inst = x64_make_inst_E2G(mov, rd, rs);
-                               X64_INST_ADD_CHECK(c->instructions, inst);
+                               src->dag_node->color = x64_find_register_color_bytes(rd->color, size)->color;
 
-                               scf_instruction_t* tmp;
-                               int j;
-                               int k;
-                               for (j = start; j < c->instructions->size; j++) {
-                                       tmp           = c->instructions->data[j];
+                               X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
 
-                                       for (k = j - 1; k >= j - start; k--)
-                                               c->instructions->data[k + 1] = c->instructions->data[k];
+                               if (rd->bytes > size) {
+                                       inst = x64_make_inst_E2G(mov, rd, rs);
+                                       X64_INST_ADD_CHECK(c->instructions, inst);
+                               }
+                       } else {
+                               X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1);
 
-                                       c->instructions->data[j - start] = tmp;
+                               if (!X64_COLOR_CONFLICT(rd->color, rs->color) || rd->bytes > size) {
+                                       inst = x64_make_inst_E2G(mov, rd, rs);
+                                       X64_INST_ADD_CHECK(c->instructions, inst);
                                }
                        }
-               } else {
-                       int ret = x64_save_reg(rd, c, f);
-                       if (ret < 0)
-                               return ret;
+               } else if (0 == src->dag_node->color) {
+                       assert(0 == is_float);
+
+                       if (rd->bytes > size)
+                               scf_variable_extend_bytes(v, rd->bytes);
 
+                       mov  = x64_find_OpCode(SCF_X64_MOV, rd->bytes, rd->bytes, SCF_X64_I2G);
+                       inst = x64_make_inst_I2G(mov, rd, (uint8_t*)&v->data, rd->bytes);
+                       X64_INST_ADD_CHECK(c->instructions, inst);
+               } else {
                        inst = x64_make_inst_M2G(&rela, mov, rd, NULL, v);
                        X64_INST_ADD_CHECK(c->instructions, inst);
                        X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL);
index 91d0545f07c2779591572ee10a5e48c65160d409..76becf1321ad47b4804be1975b22de2d6e415fb0 100644 (file)
@@ -414,6 +414,8 @@ static void _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f, i
                f->bp_used_flag = 1;
        else
                f->bp_used_flag = 0;
+
+       scf_logw("%s(), f->bp_used_flag: %d\n", f->node.w->text->data, f->bp_used_flag);
 }
 
 int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
@@ -446,7 +448,7 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
        int ret = 0;
 
        for (l = scf_list_head(&f->basic_block_list_head); l != scf_list_sentinel(&f->basic_block_list_head);
-                       l = scf_list_next(l)) {
+                = scf_list_next(l)) {
 
                bb = scf_list_data(l, scf_basic_block_t, list);
 
@@ -461,7 +463,6 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
 
                        if (dst->bb->index < bb->index)
                                jmp_back_flag = 1;
-
                        continue;
                }
 
@@ -469,9 +470,9 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f)
                        scf_vector_clear(std_insts, NULL);
 
                for (l2 = scf_list_head(&bb->code_list_head); l2 != scf_list_sentinel(&bb->code_list_head);
-                               l2 = scf_list_next(l2)) {
+                       l2  = scf_list_next(l2)) {
 
-                       c = scf_list_data(l2, scf_3ac_code_t, list);
+                       c   = scf_list_data(l2, scf_3ac_code_t, list);
 
                        if (!c->instructions)
                                continue;
@@ -528,4 +529,3 @@ error:
        scf_vector_free(std_insts);
        return ret;
 }
-
index b4bb4bae8df926751d819165e3b26130950a1094..0bec39239d82146cee12d3f4723191c32045ef3c 100644 (file)
@@ -1391,4 +1391,3 @@ int x64_pop_callee_regs(scf_3ac_code_t* c, scf_function_t* f)
 
        return 0;
 }
-
index 4f2c55557908286613243acb7e461241672e2986..832c62e652b4d0d4def1bd11da240fbd549e740b 100644 (file)
@@ -54,9 +54,9 @@ static uint32_t x64_abi_float_regs[] =
 static uint32_t x64_abi_ret_regs[] =
 {
        SCF_X64_REG_RAX,
-       SCF_X64_REG_RCX,
-       SCF_X64_REG_RDX,
        SCF_X64_REG_RDI,
+       SCF_X64_REG_RSI,
+       SCF_X64_REG_RDX,
 };
 #define X64_ABI_RET_NB (sizeof(x64_abi_ret_regs) / sizeof(x64_abi_ret_regs[0]))