fix: pointer ++ / -- / += / -= error
authoryu.dongliang <18588496441@163.com>
Sun, 6 Oct 2024 15:48:15 +0000 (23:48 +0800)
committeryu.dongliang <18588496441@163.com>
Sun, 6 Oct 2024 15:48:15 +0000 (23:48 +0800)
core/scf_expr.c
examples/pointer_add_assign.c [new file with mode: 0644]
examples/pointer_inc.c [new file with mode: 0644]
native/x64/scf_x64_inst.c
parse/scf_operator_handler_semantic.c

index 35c8eb1ec58be474e78febacec6e427379661ff2..8a8b081bc795992a5fb97747cd657322eeeeac5f 100644 (file)
@@ -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 (file)
index 0000000..5c82562
--- /dev/null
@@ -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 (file)
index 0000000..ff04d4a
--- /dev/null
@@ -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;
+}
index 690a0a4b5a214b3d2c9c2d7d9ee994b603a988ba..05d3e13ba3595f1eaaece22591608fd869ea037a 100644 (file)
@@ -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},
 
index 08b6e90895cec818fc8bc8d62f8fcbc36d9c6b1e..182d52f49fcc699f732414b1e06050cd14426a51 100644 (file)
@@ -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)
 {