+#include"scf_optimizer.h"
+#include"scf_pointer_alias.h"
+
+static int __js_teq(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* node)
+{
+ scf_3ac_code_t* c;
+ scf_variable_t* v;
+ scf_function_t* f = NULL;
+ scf_type_t* t = NULL;
+ scf_node_t* pf;
+ scf_node_t* fret;
+
+ int ret = scf_ast_find_global_function(&f, ast, "Object_teq");
+ if (ret < 0)
+ return ret;
+
+ ret = scf_ast_find_type_type(&t, ast, SCF_FUNCTION_PTR);
+ if (ret < 0)
+ return ret;
+
+ v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 1, 1, f);
+ if (!v)
+ return -ENOMEM;
+ v->const_literal_flag = 1;
+
+ pf = scf_node_alloc(NULL, v->type, v);
+ scf_variable_free(v);
+ v = NULL;
+ if (!pf)
+ return -ENOMEM;
+
+ ret = scf_ast_find_type_type(&t, ast, SCF_VAR_BOOL);
+ if (ret < 0)
+ return ret;
+
+ v = SCF_VAR_ALLOC_BY_TYPE(f->node.w, t, 0, 0, NULL);
+ if (!v)
+ return -ENOMEM;
+ v->tmp_flag = 1;
+
+ fret = scf_node_alloc(f->node.w, SCF_OP_CALL, NULL);
+ if (!fret) {
+ scf_variable_free(v);
+ scf_node_free(pf);
+ return -ENOMEM;
+ }
+ fret->op = scf_find_base_operator_by_type(SCF_OP_CALL);
+ fret->result = v;
+ v = NULL;
+
+ scf_node_t* srcs[] = {pf, node};
+
+ c = scf_3ac_code_NN(SCF_OP_CALL, &fret, 1, srcs, 2);
+ if (!c) {
+ scf_node_free(pf);
+ scf_node_free(fret);
+ return -ENOMEM;
+ }
+
+ *pc = c;
+ return 0;
+}
+
+static int _optimize_js_teq_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+ scf_3ac_operand_t* src;
+ scf_3ac_operand_t* dst;
+ scf_3ac_code_t* c;
+ scf_3ac_code_t* c2;
+ scf_variable_t* v;
+ scf_node_t* node;
+ scf_type_t* Object = NULL;
+ scf_list_t* l;
+
+ int ret = scf_ast_find_global_type(&Object, ast, "Object");
+ if (ret < 0)
+ return ret;
+
+ for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
+
+ c = scf_list_data(l, scf_3ac_code_t, list);
+ l = scf_list_next(l);
+
+ if (SCF_OP_3AC_TEQ == c->op->type) {
+ src = c->srcs->data[0];
+ node = src->node;
+
+ while (SCF_OP_EXPR == node->type)
+ node = node->nodes[0];
+
+ v = _scf_operand_get(node);
+
+ if (v->type != Object->type)
+ continue;
+
+ if (SCF_OP_CALL == node->type) {
+ assert(node->nb_nodes > 0);
+
+ scf_variable_t* v2 = _scf_operand_get(node->nodes[0]);
+ scf_function_t* f2 = v2->func_ptr;
+
+ if (!strcmp(f2->node.w->text->data, "scf__auto_malloc"))
+ continue;
+ scf_logd("f2: %s()\n", f2->node.w->text->data);
+ }
+
+ c2 = NULL;
+ ret = __js_teq(ast, &c2, node);
+ if (ret < 0)
+ return ret;
+
+ c2->basic_block = c->basic_block;
+ c2->basic_block->call_flag = 1;
+
+ scf_list_add_tail(&c->list, &c2->list);
+
+ assert(1 == c2->dsts->size);
+ dst = c2->dsts->data[0];
+
+ src->node = scf_node_clone(dst->node);
+ if (!src->node)
+ return -ENOMEM;
+ src->node->result = dst->node->result;
+ src->node->op = dst->node->op;
+ }
+ }
+
+ return 0;
+}
+
+static int _optimize_js_teq(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
+{
+ if (!f)
+ return -EINVAL;
+
+ if (strcmp(f->node.w->text->data, "__js_main")) {
+ scf_string_t* s = f->node.w->file;
+
+ if (!strncmp(s->data + s->len - 8, "js/doc.c", 8))
+ return 0;
+ }
+
+ printf("\n");
+ scf_logi("------- %s() ------ file: %s\n", f->node.w->text->data, f->node.w->file->data);
+
+ scf_list_t* bb_list_head = &f->basic_block_list_head;
+ scf_list_t* l;
+ scf_basic_block_t* bb;
+
+ if (scf_list_empty(bb_list_head))
+ return 0;
+
+ for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
+
+ bb = scf_list_data(l, scf_basic_block_t, list);
+ l = scf_list_next(l);
+
+ if (bb->cmp_flag) {
+
+ int ret = _optimize_js_teq_bb(ast, f, bb, bb_list_head);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+scf_optimizer_t scf_optimizer_js_teq =
+{
+ .name = "js_teq",
+
+ .optimize = _optimize_js_teq,
+
+ .flags = SCF_OPTIMIZER_LOCAL,
+};