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);
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)
{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},
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);
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)
{