From: yu.dongliang <18588496441@163.com> Date: Sun, 6 Oct 2024 15:48:15 +0000 (+0800) Subject: fix: pointer ++ / -- / += / -= error X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=3a96aa9293342093b0ae9c91a9d0e27b28d7dfae;p=scf.git fix: pointer ++ / -- / += / -= error --- diff --git a/core/scf_expr.c b/core/scf_expr.c index 35c8eb1..8a8b081 100644 --- a/core/scf_expr.c +++ b/core/scf_expr.c @@ -39,8 +39,7 @@ int scf_expr_copy(scf_node_t* e2, scf_node_t* e) scf_expr_t* scf_expr_clone(scf_node_t* e) { - scf_expr_t* e2 = scf_expr_alloc(); - + scf_expr_t* e2 = scf_node_clone(e); if (!e2) return NULL; diff --git a/examples/pointer_add_assign.c b/examples/pointer_add_assign.c new file mode 100644 index 0000000..5c82562 --- /dev/null +++ b/examples/pointer_add_assign.c @@ -0,0 +1,13 @@ +int printf(const char* fmt, ...); + +int main() +{ + int a[4] = {1, 2, 3, 4}; + + int* p = a; + + p += 2; + + printf("*p: %d\n", *p); + return 0; +} diff --git a/examples/pointer_inc.c b/examples/pointer_inc.c new file mode 100644 index 0000000..ff04d4a --- /dev/null +++ b/examples/pointer_inc.c @@ -0,0 +1,13 @@ +int printf(const char* fmt, ...); + +int main() +{ + int a[4] = {1, 2, 3, 4}; + + int* p = a; + + ++p; + + printf("*p: %d\n", *p); + return 0; +} diff --git a/native/x64/scf_x64_inst.c b/native/x64/scf_x64_inst.c index 690a0a4..05d3e13 100644 --- a/native/x64/scf_x64_inst.c +++ b/native/x64/scf_x64_inst.c @@ -686,42 +686,6 @@ static int _x64_inst_unary_assign(scf_native_t* ctx, scf_3ac_code_t* c, int OpCo return 0; } -static int _x64_inst_unary_post_assign(scf_native_t* ctx, scf_3ac_code_t* c, int OpCode_type) -{ - if (!c->srcs || c->srcs->size != 1) - return -EINVAL; - - if (!c->dsts || c->dsts->size != 1) - return -EINVAL; - - scf_x64_context_t* x64 = ctx->priv; - scf_function_t* f = x64->f; - scf_3ac_operand_t* src = c->srcs->data[0]; - scf_3ac_operand_t* dst = c->dsts->data[0]; - - if (!src || !src->dag_node) - return -EINVAL; - - if (!dst || !dst->dag_node) - return -EINVAL; - - if (!c->instructions) { - c->instructions = scf_vector_alloc(); - if (!c->instructions) - return -ENOMEM; - } - - scf_instruction_t* inst = NULL; - scf_register_t* rs = NULL; - scf_variable_t* var = src->dag_node->var; - - int ret = x64_inst_op2(SCF_X64_MOV, dst->dag_node, src->dag_node, c, f); - if (ret < 0) - return ret; - - return _x64_inst_unary_assign(ctx, c, OpCode_type); -} - static int _x64_inst_bit_not_handler(scf_native_t* ctx, scf_3ac_code_t* c) { return _x64_inst_unary(ctx, c, SCF_X64_NOT); @@ -801,24 +765,84 @@ static int _x64_inst_neg_handler(scf_native_t* ctx, scf_3ac_code_t* c) return 0; } -static int _x64_inst_inc_handler(scf_native_t* ctx, scf_3ac_code_t* c) +static int _x64_inst_inc(scf_native_t* ctx, scf_3ac_code_t* c, int INC, int ADD) { - return _x64_inst_unary_assign(ctx, c, SCF_X64_INC); -} + if (!c->srcs || c->srcs->size != 1) + return -EINVAL; -static int _x64_inst_inc_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) -{ - return _x64_inst_unary_post_assign(ctx, c, SCF_X64_INC); + scf_x64_context_t* x64 = ctx->priv; + scf_function_t* f = x64->f; + scf_3ac_operand_t* src = c->srcs->data[0]; + + if (!src || !src->dag_node) + return -EINVAL; + + if (0 == src->dag_node->color) + return -EINVAL; + + scf_variable_t* v = src->dag_node->var; + scf_register_t* rs = NULL; + scf_x64_OpCode_t* OpCode; + scf_instruction_t* inst = NULL; + + int imm_size = 1; + if (v->data_size > 0xff) + imm_size = 4; + + if (v->nb_pointers > 0) + OpCode = x64_find_OpCode(ADD, imm_size, v->size, SCF_X64_I2E); + else + OpCode = x64_find_OpCode(INC, v->size, v->size, SCF_X64_E); + + if (!OpCode) { + scf_loge("v->size: %d, imm_size: %d\n", v->size, imm_size); + return -EINVAL; + } + + if (!c->instructions) { + c->instructions = scf_vector_alloc(); + if (!c->instructions) + return -ENOMEM; + } + + if (v->nb_pointers > 0) { + if (src->dag_node->color > 0) { + X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + inst = x64_make_inst_I2E(OpCode, rs, (uint8_t*)&v->data_size, imm_size); + X64_INST_ADD_CHECK(c->instructions, inst); + } else { + scf_rela_t* rela = NULL; + + inst = x64_make_inst_I2M(&rela, OpCode, v, NULL, (uint8_t*)&v->data_size, imm_size); + X64_INST_ADD_CHECK(c->instructions, inst); + X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + } + + } else { + if (src->dag_node->color > 0) { + X64_SELECT_REG_CHECK(&rs, src->dag_node, c, f, 1); + inst = x64_make_inst_E(OpCode, rs); + X64_INST_ADD_CHECK(c->instructions, inst); + } else { + scf_rela_t* rela = NULL; + + inst = x64_make_inst_M(&rela, OpCode, v, NULL); + X64_INST_ADD_CHECK(c->instructions, inst); + X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + } + } + + return 0; } -static int _x64_inst_dec_handler(scf_native_t* ctx, scf_3ac_code_t* c) +static int _x64_inst_inc_handler(scf_native_t* ctx, scf_3ac_code_t* c) { - return _x64_inst_unary_assign(ctx, c, SCF_X64_DEC); + return _x64_inst_inc(ctx, c, SCF_X64_INC, SCF_X64_ADD); } -static int _x64_inst_dec_post_handler(scf_native_t* ctx, scf_3ac_code_t* c) +static int _x64_inst_dec_handler(scf_native_t* ctx, scf_3ac_code_t* c) { - return _x64_inst_unary_post_assign(ctx, c, SCF_X64_DEC); + return _x64_inst_inc(ctx, c, SCF_X64_DEC, SCF_X64_SUB); } static int _x64_inst_pointer_handler(scf_native_t* ctx, scf_3ac_code_t* c) @@ -2130,9 +2154,6 @@ static x64_inst_handler_t x64_inst_handlers[] = { {SCF_OP_INC, _x64_inst_inc_handler}, {SCF_OP_DEC, _x64_inst_dec_handler}, - {SCF_OP_INC_POST, _x64_inst_inc_post_handler}, - {SCF_OP_DEC_POST, _x64_inst_dec_post_handler}, - {SCF_OP_DEREFERENCE, _x64_inst_dereference_handler}, {SCF_OP_ADDRESS_OF, _x64_inst_address_of_handler}, diff --git a/parse/scf_operator_handler_semantic.c b/parse/scf_operator_handler_semantic.c index 08b6e90..182d52f 100644 --- a/parse/scf_operator_handler_semantic.c +++ b/parse/scf_operator_handler_semantic.c @@ -2089,6 +2089,185 @@ static int _semantic_pointer_add(scf_ast_t* ast, scf_node_t* parent, scf_node_t* return 0; } +static int _semantic_pointer_add_assign(scf_ast_t* ast, scf_node_t* parent, scf_node_t* pointer, scf_node_t* index) +{ + scf_variable_t* v = _scf_operand_get(pointer); + scf_variable_t* r = NULL; + scf_type_t* t = NULL; + scf_node_t* p2; + scf_node_t* add; + + int ret = scf_ast_find_type_type(&t, ast, v->type); + if (ret < 0) + return ret; + + add = scf_node_alloc(parent->w, SCF_OP_ADD, NULL); + if (!add) + return -ENOMEM; + + r = SCF_VAR_ALLOC_BY_TYPE(parent->w, t, v->const_flag, scf_variable_nb_pointers(v), v->func_ptr); + if (!r) { + scf_node_free(add); + return -ENOMEM; + } + r->local_flag = 1; + r->tmp_flag = 1; + + add->result = r; + r = NULL; + + p2 = scf_expr_clone(pointer); + if (!p2) { + scf_node_free(add); + return -ENOMEM; + } + + if (scf_type_is_var(pointer->type)) + p2->var = scf_variable_ref(pointer->var); + + else if (scf_type_is_operator(pointer->type)) + p2->result = scf_variable_ref(pointer->result); + + ret = scf_node_add_child(add, p2); + if (ret < 0) { + scf_node_free(p2); + scf_node_free(add); + return ret; + } + + ret = scf_node_add_child(add, index); + if (ret < 0) { + scf_node_free(add); + return ret; + } + + parent->nodes[1] = NULL; + + ret = _semantic_pointer_add(ast, add, p2, index); + if (ret < 0) { + scf_node_free(add); + return ret; + } + + parent->nodes[1] = add; + + add->parent = parent; + parent->op = scf_find_base_operator_by_type(SCF_OP_ASSIGN); + parent->type = SCF_OP_ASSIGN; + return 0; +} + +static int _scf_op_semantic_binary_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) +{ + assert(2 == nb_nodes); + + scf_handler_data_t* d = data; + + scf_variable_t* v0 = _scf_operand_get(nodes[0]); + scf_variable_t* v1 = _scf_operand_get(nodes[1]); + scf_variable_t* v2 = NULL; + scf_node_t* parent = nodes[0]->parent; + + assert(v0); + assert(v1); + + if (v0->const_flag || v0->nb_dimentions > 0) { + scf_loge("const var '%s' can't be assigned\n", v0->w->text->data); + return -1; + } + + if (scf_variable_is_struct_pointer(v0) || scf_variable_is_struct_pointer(v1)) { + + int ret = _semantic_do_overloaded(ast, nodes, nb_nodes, d); + if (0 == ret) + return 0; + + if (-404 != ret) { + scf_loge("semantic do overloaded error\n"); + return -1; + } + } + + if (scf_variable_integer(v0) || scf_variable_float(v0)) { + + if (scf_variable_integer(v1) || scf_variable_float(v1)) { + + scf_type_t* t = NULL; + + int nb_pointers0 = scf_variable_nb_pointers(v0); + int nb_pointers1 = scf_variable_nb_pointers(v1); + + if (nb_pointers0 > 0) { + + if (nb_pointers1 > 0) { + + if (!scf_variable_same_type(v0, v1)) { + scf_loge("different type pointer, type: %d,%d, nb_pointers: %d,%d\n", + v0->type, v1->type, nb_pointers0, nb_pointers1); + return -EINVAL; + } + + } else if (!scf_variable_integer(v1)) { + scf_loge("var calculated with a pointer should be a interger\n"); + return -EINVAL; + } else { + t = scf_block_find_type_type(ast->current_block, SCF_VAR_UINTPTR); + + v2 = SCF_VAR_ALLOC_BY_TYPE(v1->w, t, v1->const_flag, 0, NULL); + + int ret = _semantic_add_type_cast(ast, &nodes[1], v2, nodes[1]); + + scf_variable_free(v2); + v2 = NULL; + if (ret < 0) { + scf_loge("add type cast failed\n"); + return ret; + } + + if (SCF_OP_ADD_ASSIGN == parent->type || SCF_OP_SUB_ASSIGN == parent->type) { + + ret = _semantic_pointer_add_assign(ast, parent, nodes[0], nodes[1]); + if (ret < 0) + return ret; + } + } + } else if (nb_pointers1 > 0) { + scf_loge("assign a pointer to an integer NOT with a type cast, file: %s, line: %d\n", parent->w->file->data, parent->w->line); + return -1; + + } else if (v0->type != v1->type) { + + if (scf_type_cast_check(ast, v0, v1) < 0) { + scf_loge("type cast failed, file: %s, line: %d\n", parent->w->file->data, parent->w->line); + return -1; + } + + int ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); + if (ret < 0) { + scf_loge("add type cast failed\n"); + return ret; + } + } + + int ret = scf_ast_find_type_type(&t, ast, v0->type); + if (ret < 0) + return ret; + assert(t); + + scf_lex_word_t* w = nodes[0]->parent->w; + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(w, t, v0->const_flag, v0->nb_pointers, v0->func_ptr); + if (!r) + return -ENOMEM; + + *d->pret = r; + return 0; + } + } + + scf_loge("type %d, %d not support\n", v0->type, v1->type); + return -1; +} + static int _scf_op_semantic_binary(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { assert(2 == nb_nodes); @@ -2624,76 +2803,6 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no return 0; } -static int _scf_op_semantic_binary_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) -{ - assert(2 == nb_nodes); - - scf_handler_data_t* d = data; - - scf_variable_t* v0 = _scf_operand_get(nodes[0]); - scf_variable_t* v1 = _scf_operand_get(nodes[1]); - scf_node_t* parent = nodes[0]->parent; - - assert(v0); - assert(v1); - - if (v0->const_flag || v0->nb_dimentions > 0) { - scf_loge("const var '%s' can't be assigned\n", v0->w->text->data); - return -1; - } - - if (scf_variable_is_struct_pointer(v0) || scf_variable_is_struct_pointer(v1)) { - - int ret = _semantic_do_overloaded(ast, nodes, nb_nodes, d); - if (0 == ret) - return 0; - - if (-404 != ret) { - scf_loge("semantic do overloaded error\n"); - return -1; - } - } - - if (scf_variable_integer(v0) || scf_variable_float(v0)) { - - if (scf_variable_integer(v1) || scf_variable_float(v1)) { - - if (!scf_variable_same_type(v0, v1)) { - - if (scf_type_cast_check(ast, v0, v1) < 0) { - scf_loge("\n"); - return -1; - } - - int ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); - if (ret < 0) { - scf_loge("add type cast failed\n"); - return ret; - } - } - - scf_type_t* t = NULL; - int ret = scf_ast_find_type_type(&t, ast, v0->type); - if (ret < 0) - return ret; - assert(t); - - scf_lex_word_t* w = nodes[0]->parent->w; - scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(w, t, v0->const_flag, v0->nb_pointers, v0->func_ptr); - if (!r) { - scf_loge("var alloc failed\n"); - return -ENOMEM; - } - - *d->pret = r; - } - } else { - scf_loge("type %d, %d not support\n", v0->type, v1->type); - return -1; - } - - return 0; -} static int _scf_op_semantic_binary_interger_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) {