From fb78fc0784c958890708c6474763ad7791037a99 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Tue, 19 Aug 2025 16:10:38 +0800 Subject: [PATCH] fix: x64 xmm registers, update function signature --- core/scf_ast.c | 167 +++++++++++++++++++++++++++++++++++++++ core/scf_ast.h | 6 +- core/scf_function.c | 86 -------------------- core/scf_function.h | 2 - native/x64/scf_x64_reg.c | 123 ++++++++++++++-------------- native/x64/scf_x64_reg.h | 43 ++++++---- parse/scf_dfa_expr.c | 2 +- parse/scf_parse.c | 4 +- 8 files changed, 260 insertions(+), 173 deletions(-) diff --git a/core/scf_ast.c b/core/scf_ast.c index a85bc7f..e3fd536 100644 --- a/core/scf_ast.c +++ b/core/scf_ast.c @@ -410,3 +410,170 @@ int scf_ast_find_type_type(scf_type_t** pt, scf_ast_t* ast, int type) return scf_ast_find_global_type_type(pt, ast, type); } +int scf_ast_add_const_str(scf_ast_t* ast, scf_node_t* parent, scf_lex_word_t* w) +{ + scf_variable_t* v; + scf_lex_word_t* w2; + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_CHAR); + scf_node_t* node; + + w2 = scf_lex_word_clone(w); + if (!w2) + return -ENOMEM; + + int ret = scf_string_cat_cstr(w2->text, "__cstr"); + if (ret < 0) { + scf_lex_word_free(w2); + return ret; + } + + v = SCF_VAR_ALLOC_BY_TYPE(w2, t, 1, 1, NULL); + scf_lex_word_free(w2); + w2 = NULL; + if (!v) + return -ENOMEM; + v->const_literal_flag = 1; + + scf_logi("w->text: %s\n", w->text->data); + v->data.s = scf_string_clone(w->text); + if (!v->data.s) { + scf_variable_free(v); + return -ENOMEM; + } + + node = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + if (!node) + return -ENOMEM; + + ret = scf_node_add_child(parent, node); + if (ret < 0) { + scf_node_free(node); + return ret; + } + + return 0; +} + +int scf_ast_add_const_var(scf_ast_t* ast, scf_node_t* parent, int type, const uint64_t u64) +{ + scf_variable_t* v; + scf_type_t* t = scf_block_find_type_type(ast->current_block, type); + scf_node_t* node; + + v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 1, 0, NULL); + if (!v) + return -ENOMEM; + v->data.u64 = u64; + v->const_literal_flag = 1; + + node = scf_node_alloc(NULL, v->type, v); + scf_variable_free(v); + v = NULL; + if (!node) + return -ENOMEM; + + int ret = scf_node_add_child(parent, node); + if (ret < 0) { + scf_node_free(node); + return ret; + } + + return 0; +} + +int scf_function_signature(scf_ast_t* ast, scf_function_t* f) +{ + scf_string_t* s; + scf_type_t* t = (scf_type_t*)f->node.parent; + + int ret; + int i; + + s = scf_string_alloc(); + if (!s) + return -ENOMEM; + + if (t->node.type >= SCF_STRUCT) { + assert(t->node.class_flag); + + ret = scf_string_cat(s, t->name); + if (ret < 0) + goto error; + + ret = scf_string_cat_cstr(s, "_"); + if (ret < 0) + goto error; + } + + if (f->op_type >= 0) { + scf_operator_t* op = scf_find_base_operator_by_type(f->op_type); + + if (!op->signature) + goto error; + + ret = scf_string_cat_cstr(s, op->signature); + } else + ret = scf_string_cat(s, f->node.w->text); + + if (ret < 0) + goto error; + scf_logd("f signature: %s\n", s->data); + + if (t->node.type < SCF_STRUCT) { + if (f->signature) + scf_string_free(f->signature); + + f->signature = s; + return 0; + } + + if (f->argv) { + for (i = 0; i < f->argv->size; i++) { + scf_variable_t* v = f->argv->data[i]; + scf_type_t* t_v = NULL; + + t_v = scf_block_find_type_type((scf_block_t*)t, v->type); + if (!t_v) { + ret = scf_ast_find_global_type_type(&t_v, ast, v->type); + if (ret < 0) + goto error; + } + + ret = scf_string_cat_cstr(s, "_"); + if (ret < 0) + goto error; + + scf_logd("t_v: %p, v->type: %d, v->w->text->data: %s\n", t_v, v->type, v->w->text->data); + + const char* abbrev = scf_type_find_abbrev(t_v->name->data); + if (abbrev) + ret = scf_string_cat_cstr(s, abbrev); + else + ret = scf_string_cat(s, t_v->name); + if (ret < 0) + goto error; + + if (v->nb_pointers > 0) { + char buf[64]; + snprintf(buf, sizeof(buf) - 1, "%d", v->nb_pointers); + + ret = scf_string_cat_cstr(s, buf); + if (ret < 0) + goto error; + } + } + } + + scf_logd("f signature: %s\n", s->data); + + if (f->signature) + scf_string_free(f->signature); + f->signature = s; + return 0; + +error: + scf_string_free(s); + return -1; +} diff --git a/core/scf_ast.h b/core/scf_ast.h index 404c778..dbd9169 100644 --- a/core/scf_ast.h +++ b/core/scf_ast.h @@ -101,5 +101,9 @@ int scf_ast_add_base_type(scf_ast_t* ast, scf_base_type_t* base_type); int scf_ast_add_file_block(scf_ast_t* ast, const char* path); -#endif +int scf_function_signature(scf_ast_t* ast, scf_function_t* f); + +int scf_ast_add_const_str(scf_ast_t* ast, scf_node_t* parent, scf_lex_word_t* w); +int scf_ast_add_const_var(scf_ast_t* ast, scf_node_t* parent, int type, const uint64_t u64); +#endif diff --git a/core/scf_function.c b/core/scf_function.c index 1b537a4..4fe5bef 100644 --- a/core/scf_function.c +++ b/core/scf_function.c @@ -215,89 +215,3 @@ int scf_function_same_type(scf_function_t* f0, scf_function_t* f1) return scf_function_same_argv(f0->argv, f1->argv); } - -int scf_function_signature(scf_function_t* f) -{ - scf_string_t* s; - scf_type_t* t = (scf_type_t*)f->node.parent; - - int ret; - int i; - - s = scf_string_alloc(); - if (!s) - return -ENOMEM; - - if (t->node.type >= SCF_STRUCT) { - assert(t->node.class_flag); - - ret = scf_string_cat(s, t->name); - if (ret < 0) - goto error; - - ret = scf_string_cat_cstr(s, "_"); - if (ret < 0) - goto error; - } - - if (f->op_type >= 0) { - scf_operator_t* op = scf_find_base_operator_by_type(f->op_type); - - if (!op->signature) - goto error; - - ret = scf_string_cat_cstr(s, op->signature); - } else - ret = scf_string_cat(s, f->node.w->text); - - if (ret < 0) - goto error; - scf_logd("f signature: %s\n", s->data); - - if (t->node.type < SCF_STRUCT) { - if (f->signature) - scf_string_free(f->signature); - - f->signature = s; - return 0; - } - - if (f->argv) { - for (i = 0; i < f->argv->size; i++) { - scf_variable_t* v = f->argv->data[i]; - scf_type_t* t_v = scf_block_find_type_type((scf_block_t*)t, v->type); - - ret = scf_string_cat_cstr(s, "_"); - if (ret < 0) - goto error; - - const char* abbrev = scf_type_find_abbrev(t_v->name->data); - if (abbrev) - ret = scf_string_cat_cstr(s, abbrev); - else - ret = scf_string_cat(s, t_v->name); - if (ret < 0) - goto error; - - if (v->nb_pointers > 0) { - char buf[64]; - snprintf(buf, sizeof(buf) - 1, "%d", v->nb_pointers); - - ret = scf_string_cat_cstr(s, buf); - if (ret < 0) - goto error; - } - } - } - - scf_logd("f signature: %s\n", s->data); - - if (f->signature) - scf_string_free(f->signature); - f->signature = s; - return 0; - -error: - scf_string_free(s); - return -1; -} diff --git a/core/scf_function.h b/core/scf_function.h index 9765f2a..4ca3b64 100644 --- a/core/scf_function.h +++ b/core/scf_function.h @@ -74,6 +74,4 @@ int scf_function_same_type(scf_function_t* f0, scf_function_t* f1); int scf_function_same_argv(scf_vector_t* argv0, scf_vector_t* argv1); int scf_function_like_argv(scf_vector_t* argv0, scf_vector_t* argv1); -int scf_function_signature(scf_function_t* f); - #endif diff --git a/native/x64/scf_x64_reg.c b/native/x64/scf_x64_reg.c index 331d25d..765e4ed 100644 --- a/native/x64/scf_x64_reg.c +++ b/native/x64/scf_x64_reg.c @@ -207,18 +207,21 @@ void x64_registers_print() } } -int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs) +int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs) { scf_basic_block_t* bb = c->basic_block; scf_dag_node_t* dn; scf_instruction_t* inst; - scf_x64_OpCode_t* push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G); - scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8,8, SCF_X64_G2E); - scf_register_t* rsp = x64_find_register("rsp"); + scf_x64_OpCode_t* push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G); + scf_x64_OpCode_t* movsd = x64_find_OpCode(SCF_X64_MOVSD, 8,8, SCF_X64_G2E); + scf_x64_OpCode_t* mov = x64_find_OpCode(SCF_X64_MOV, 8,8, SCF_X64_G2E); + scf_x64_OpCode_t* sub = x64_find_OpCode(SCF_X64_SUB, 4,4, SCF_X64_I2E); + scf_register_t* rsp = x64_find_register("rsp"); scf_register_t* r; scf_register_t* r2; + uint32_t imm = 8; int i; int j; int k; @@ -226,7 +229,7 @@ int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int sta int n = 0; for (j = 0; j < nb_regs; j++) { - r2 = x64_find_register_type_id_bytes(0, regs[j], 8); + r2 = x64_find_register(regs[j]); for (i = 0; i < sizeof(x64_registers) / sizeof(x64_registers[0]); i++) { r = &(x64_registers[i]); @@ -263,10 +266,21 @@ int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int sta if (i == sizeof(x64_registers) / sizeof(x64_registers[0])) continue; - if (stack_size > 0) - inst = x64_make_inst_G2P(mov, rsp, size + stack_size, r2); - else - inst = x64_make_inst_G(push, r2); + if (X64_COLOR_TYPE(r2->color)) { + if (stack_size > 0) + inst = x64_make_inst_G2P(movsd, rsp, size + stack_size, r2); + else { + inst = x64_make_inst_I2E(sub, rsp, (uint8_t*)&imm, 4); + X64_INST_ADD_CHECK(c->instructions, inst); + + inst = x64_make_inst_G2P(movsd, rsp, 0, r2); + } + } else { + if (stack_size > 0) + inst = x64_make_inst_G2P(mov, rsp, size + stack_size, r2); + else + inst = x64_make_inst_G(push, r2); + } X64_INST_ADD_CHECK(c->instructions, inst); saved_regs[n++] = r2; @@ -276,10 +290,21 @@ int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int sta if (size & 0xf) { r2 = saved_regs[n - 1]; - if (stack_size > 0) - inst = x64_make_inst_G2P(mov, rsp, size + stack_size, r2); - else - inst = x64_make_inst_G(push, r2); + if (X64_COLOR_TYPE(r2->color)) { + if (stack_size > 0) + inst = x64_make_inst_G2P(movsd, rsp, size + stack_size, r2); + else { + inst = x64_make_inst_I2E(sub, rsp, (uint8_t*)&imm, 4); + X64_INST_ADD_CHECK(c->instructions, inst); + + inst = x64_make_inst_G2P(movsd, rsp, 0, r2); + } + } else { + if (stack_size > 0) + inst = x64_make_inst_G2P(mov, rsp, size + stack_size, r2); + else + inst = x64_make_inst_G(push, r2); + } X64_INST_ADD_CHECK(c->instructions, inst); saved_regs[n++] = r2; @@ -297,53 +322,19 @@ int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int sta return size; } -int x64_push_regs(scf_vector_t* instructions, uint32_t* regs, int nb_regs) -{ - int i; - int j; - scf_register_t* r; - scf_register_t* r2; - scf_instruction_t* inst; - scf_x64_OpCode_t* push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G); - - for (j = 0; j < nb_regs; j++) { - r2 = x64_find_register_type_id_bytes(0, regs[j], 8); - - for (i = 0; i < sizeof(x64_registers) / sizeof(x64_registers[0]); i++) { - r = &(x64_registers[i]); - - if (!X64_COLOR_TYPE(r->color) && (SCF_X64_REG_RSP == r->id || SCF_X64_REG_RBP == r->id)) - continue; - - if (0 == r->dag_nodes->size) - continue; - - if (X64_COLOR_CONFLICT(r2->color, r->color)) - break; - } - - if (i == sizeof(x64_registers) / sizeof(x64_registers[0])) - continue; - - inst = x64_make_inst_G(push, r2); - X64_INST_ADD_CHECK(instructions, inst); - } - return 0; -} - int x64_pop_regs(scf_vector_t* instructions, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated) { - int i; - int j; - - scf_register_t* rsp = x64_find_register("rsp"); - scf_register_t* r; - scf_register_t* r2; + scf_register_t* rsp = x64_find_register("rsp"); + scf_register_t* r; + scf_register_t* r2; scf_instruction_t* inst; - scf_x64_OpCode_t* pop = x64_find_OpCode(SCF_X64_POP, 8, 8, SCF_X64_G); - scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 4, 4, SCF_X64_I2E); + scf_x64_OpCode_t* movsd = x64_find_OpCode(SCF_X64_MOVSD, 8, 8, SCF_X64_E2G); + scf_x64_OpCode_t* pop = x64_find_OpCode(SCF_X64_POP, 8, 8, SCF_X64_G); + scf_x64_OpCode_t* add = x64_find_OpCode(SCF_X64_ADD, 4, 4, SCF_X64_I2E); uint32_t imm = 8; + int i; + int j; for (j = nb_regs - 1; j >= 0; j--) { r2 = regs[j]; @@ -373,7 +364,13 @@ int x64_pop_regs(scf_vector_t* instructions, scf_register_t** regs, int nb_regs, } if (i == nb_updated) { - inst = x64_make_inst_G(pop, r2); + if (X64_COLOR_TYPE(r2->color)) { + inst = x64_make_inst_P2G(movsd, r2, rsp, 0); + X64_INST_ADD_CHECK(instructions, inst); + + inst = x64_make_inst_I2E(add, rsp, (uint8_t*)&imm, 4); + } else + inst = x64_make_inst_G(pop, r2); X64_INST_ADD_CHECK(instructions, inst); } else { inst = x64_make_inst_I2E(add, rsp, (uint8_t*)&imm, 4); @@ -679,7 +676,7 @@ int x64_overflow_reg2(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, int x64_reg_used(scf_register_t* r, scf_dag_node_t* dn) { scf_register_t* r2; - scf_dag_node_t* dn2; + scf_dag_node_t* dn2; int i; int j; @@ -695,7 +692,7 @@ int x64_reg_used(scf_register_t* r, scf_dag_node_t* dn) continue; for (j = 0; j < r2->dag_nodes->size; j++) { - dn2 = r2->dag_nodes->data[j]; + dn2 = r2->dag_nodes->data[j]; if (dn2 != dn) return 1; @@ -745,6 +742,8 @@ scf_register_t* x64_select_overflowed_reg(scf_dag_node_t* dn, scf_3ac_code_t* c) int i; int j; + scf_logd("bytes: %d\n", bytes); + assert(c->rcg); ret = x64_rcg_find_node(&gn, c->rcg, dn, NULL); @@ -1358,9 +1357,7 @@ int x64_push_callee_regs(scf_3ac_code_t* c, scf_function_t* f) int j; for (i = 0; i < X64_ABI_CALLEE_SAVES_NB; i++) { - - j = x64_abi_callee_saves[i]; - r = x64_find_register_type_id_bytes(0, j, 8); + r = x64_find_register(x64_abi_callee_saves[i]); for (j = 0; j < N; j++) { r2 = &(x64_registers[j]); @@ -1397,9 +1394,7 @@ int x64_pop_callee_regs(scf_3ac_code_t* c, scf_function_t* f) f->callee_saved_size = 0; for (i = X64_ABI_CALLEE_SAVES_NB - 1; i >= 0; i--) { - - j = x64_abi_callee_saves[i]; - r = x64_find_register_type_id_bytes(0, j, 8); + r = x64_find_register(x64_abi_callee_saves[i]); for (j = 0; j < N; j++) { r2 = &(x64_registers[j]); diff --git a/native/x64/scf_x64_reg.h b/native/x64/scf_x64_reg.h index 790ce54..40c5967 100644 --- a/native/x64/scf_x64_reg.h +++ b/native/x64/scf_x64_reg.h @@ -65,27 +65,36 @@ static uint32_t x64_abi_ret_regs[] = }; #define X64_ABI_RET_NB (sizeof(x64_abi_ret_regs) / sizeof(x64_abi_ret_regs[0])) -static uint32_t x64_abi_caller_saves[] = +static const char* x64_abi_caller_saves[] = { - SCF_X64_REG_RAX, - SCF_X64_REG_RCX, - SCF_X64_REG_RDX, - SCF_X64_REG_RSI, - SCF_X64_REG_RDI, - SCF_X64_REG_R8, - SCF_X64_REG_R9, - SCF_X64_REG_R10, - SCF_X64_REG_R11, + "rax", + "rcx", + "rdx", + "rsi", + "rdi", + "r8", + "r9", + "r10", + "r11", + + "xmm0", + "xmm1", + "xmm2", + "xmm3", + "xmm4", + "xmm5", + "xmm6", + "xmm7", }; #define X64_ABI_CALLER_SAVES_NB (sizeof(x64_abi_caller_saves) / sizeof(x64_abi_caller_saves[0])) -static uint32_t x64_abi_callee_saves[] = +static const char* x64_abi_callee_saves[] = { - SCF_X64_REG_RBX, - SCF_X64_REG_R12, - SCF_X64_REG_R13, - SCF_X64_REG_R14, - SCF_X64_REG_R15, + "rbx", + "r12", + "r13", + "r14", + "r15", }; #define X64_ABI_CALLEE_SAVES_NB (sizeof(x64_abi_callee_saves) / sizeof(x64_abi_callee_saves[0])) @@ -138,7 +147,7 @@ int x64_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac int x64_push_regs(scf_vector_t* instructions, uint32_t* regs, int nb_regs); int x64_pop_regs (scf_vector_t* instructions, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated); -int x64_caller_save_regs(scf_3ac_code_t* c, uint32_t* regs, int nb_regs, int stack_size, scf_register_t** saved_regs); +int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs); int x64_push_callee_regs(scf_3ac_code_t* c, scf_function_t* f); int x64_pop_callee_regs (scf_3ac_code_t* c, scf_function_t* f); diff --git a/parse/scf_dfa_expr.c b/parse/scf_dfa_expr.c index 39575f0..e8e431e 100644 --- a/parse/scf_dfa_expr.c +++ b/parse/scf_dfa_expr.c @@ -197,7 +197,7 @@ static int _expr_action_number(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } - if (scf_function_signature(f) < 0) + if (scf_function_signature(parse->ast, f) < 0) return SCF_DFA_ERROR; w->text->data[2] = '\0'; diff --git a/parse/scf_parse.c b/parse/scf_parse.c index 966557a..040a42e 100644 --- a/parse/scf_parse.c +++ b/parse/scf_parse.c @@ -1937,7 +1937,7 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, for (j = 0; j < f->text_relas->size; j++) { r = f->text_relas->data[j]; - if (scf_function_signature(r->func) < 0) { + if (scf_function_signature(parse->ast, r->func) < 0) { scf_loge("\n"); goto error; } @@ -2234,7 +2234,7 @@ int64_t scf_parse_fill_code2(scf_parse_t* parse, scf_vector_t* functions, scf_ve return ret; } - if (scf_function_signature(f) < 0) + if (scf_function_signature(parse->ast, f) < 0) return -ENOMEM; int ret = _fill_function_inst(code, f, offset, parse); -- 2.25.1