support auto gc for multi-return-values
authoryu.dongliang <18588496441@163.com>
Sat, 12 Oct 2024 16:39:35 +0000 (00:39 +0800)
committeryu.dongliang <18588496441@163.com>
Sat, 12 Oct 2024 16:39:35 +0000 (00:39 +0800)
24 files changed:
core/scf_3ac.c
core/scf_auto_gc_3ac.c
core/scf_auto_gc_find.c
core/scf_basic_block.c
core/scf_basic_block.h
core/scf_core_types.h
core/scf_dag.c
core/scf_dag.h
core/scf_function.c
core/scf_function.h
core/scf_operator.c
core/scf_operator.h
core/scf_optimizer_auto_gc.c
core/scf_optimizer_auto_gc_find.c
core/scf_optimizer_generate_loads_saves.c
examples/auto_gc_multi_rets.c [new file with mode: 0644]
examples/mat.c
native/risc/scf_risc_inst.c
native/risc/scf_risc_rcg.c
native/x64/scf_x64_inst.c
native/x64/scf_x64_rcg.c
parse/scf_dfa_function.c
parse/scf_dfa_operator.c
parse/scf_operator_handler_semantic.c

index 5f0374e1b2ea4ec4e835e5fa3a0889119c6376cb..ba6507428edf3acf3c69e07d7088add106d0a34b 100644 (file)
@@ -102,8 +102,8 @@ static scf_3ac_operator_t _3ac_operators[] = {
        {SCF_OP_3AC_RELOAD,      "reload"},
        {SCF_OP_3AC_RESAVE,      "resave"},
 
-       {SCF_OP_3AC_PUSH_RAX,    "push rax"},
-       {SCF_OP_3AC_POP_RAX,     "pop  rax"},
+       {SCF_OP_3AC_PUSH_RETS,   "push rets"},
+       {SCF_OP_3AC_POP_RETS,    "pop  rets"},
        {SCF_OP_3AC_MEMSET,      "memset"},
 
        {SCF_OP_3AC_INC,         "inc3"},
index ca34c271c87d5ee42d33a0606e0cfa41df215ba0..5006aef67d20c3e48e9ab18d1c6db8a34907a708 100644 (file)
@@ -1070,7 +1070,7 @@ static int _bb_add_gc_code_ref(scf_list_t* dag_list_head, scf_ast_t* ast, scf_ba
        scf_list_t     h;
        scf_list_init(&h);
 
-       if (scf_vector_add_unique(bb->dn_reloads, ds->dag_node) < 0)
+       if (scf_vector_add_unique(bb->entry_dn_actives, ds->dag_node) < 0)
                return -ENOMEM;
 
        int ret = _auto_gc_code_list_ref(&h, dag_list_head, ast, ds);
@@ -1086,7 +1086,7 @@ static int _bb_add_gc_code_freep(scf_list_t* dag_list_head, scf_ast_t* ast, scf_
        scf_list_t     h;
        scf_list_init(&h);
 
-       if (scf_vector_add_unique(bb->dn_reloads, ds->dag_node) < 0)
+       if (scf_vector_add_unique(bb->entry_dn_actives, ds->dag_node) < 0)
                return -ENOMEM;
 
        int ret = _auto_gc_code_list_freep(&h, dag_list_head, ast, ds);
@@ -1102,7 +1102,7 @@ static int _bb_add_gc_code_memset_array(scf_list_t* dag_list_head, scf_ast_t* as
        scf_list_t     h;
        scf_list_init(&h);
 
-       if (scf_vector_add_unique(bb->dn_reloads, dn_array) < 0)
+       if (scf_vector_add_unique(bb->entry_dn_actives, dn_array) < 0)
                return -ENOMEM;
 
        int ret = _auto_gc_code_list_memset_array(&h, dag_list_head, ast, dn_array);
@@ -1118,7 +1118,7 @@ static int _bb_add_gc_code_free_array(scf_list_t* dag_list_head, scf_ast_t* ast,
        scf_list_t     h;
        scf_list_init(&h);
 
-       if (scf_vector_add_unique(bb->dn_reloads, dn_array) < 0)
+       if (scf_vector_add_unique(bb->entry_dn_actives, dn_array) < 0)
                return -ENOMEM;
 
        int ret = _auto_gc_code_list_free_array(&h, dag_list_head, ast, dn_array);
index 8e8d595532346913ebe3d9b62a441b9c89835fa5..012d2dfe9c97312f4bedeec1389ddf61e7fb0572 100644 (file)
@@ -193,7 +193,7 @@ static int _auto_gc_find_argv_in(scf_basic_block_t* cur_bb, scf_3ac_code_t* c)
 
                scf_logd("v: %s\n", v->w->text->data);
 
-               if (scf_vector_add_unique(cur_bb->dn_reloads, dn) < 0)
+               if (scf_vector_add_unique(cur_bb->entry_dn_actives, dn) < 0)
                        return -ENOMEM;
        }
 
@@ -225,12 +225,18 @@ static int _auto_gc_bb_next_find(scf_basic_block_t* bb, void* data, scf_vector_t
 
                        ds2 = scf_vector_find_cmp(next_bb->ds_malloced, ds, scf_ds_cmp_like_indexes);
                        if (ds2) {
-                               uint32_t tmp = ds2->ret;
+                               uint32_t tmp = ds2->ret_flag;
 
-                               ds2->ret |= ds->ret;
+                               ds2->ret_flag |= ds->ret_flag;
+
+                               if (tmp != ds2->ret_flag) {
+                                       scf_logd("*** ds2: %#lx, ret_index: %d, ret_flag: %d, ds: %#lx, ret_index: %d, ret_flag: %d\n",
+                                                       0xffff & (uintptr_t)ds2, ds2->ret_index, ds2->ret_flag,
+                                                       0xffff & (uintptr_t)ds,   ds->ret_index,  ds->ret_flag);
 
-                               if (tmp != ds2->ret)
                                        count++;
+                                       ds2->ret_index = ds->ret_index;
+                               }
                                continue;
                        }
 
index 3ea1b5f40f434e3ef90a2a82050359c6018b726c..9939875ce538236f2170f7926f1c17c71651ceb1 100644 (file)
@@ -90,7 +90,6 @@ scf_basic_block_t* scf_basic_block_alloc()
        if (!bb->ds_freed)
                goto error_freed;
 
-       bb->generate_flag = 1;
        return bb;
 
 error_freed:
index 49c12801a09366e94166801de74c13cc55de6bdd..eec1060880d23d24e8789968a3b4c02c52f3a5ec 100644 (file)
@@ -95,8 +95,6 @@ struct scf_basic_block_s
        uint32_t        auto_ref_flag :1;
        uint32_t        auto_free_flag:1;
 
-       uint32_t        generate_flag :1;
-
        uint32_t        back_flag   :1;
        uint32_t        loop_flag   :1;
        uint32_t        group_flag  :1;
index 956acab6772ab0321114c4bd84ebdb0fb4a0a246..a3e8468ef635c8f85302723d0fa021c01d6d3c7a 100644 (file)
@@ -193,8 +193,8 @@ enum scf_core_types
        SCF_OP_3AC_PUSH,    // push a var to stack,  only for 3ac & native
        SCF_OP_3AC_POP,     // pop a var from stack, only for 3ac & native
 
-       SCF_OP_3AC_PUSH_RAX, // push rax, only for 3ac & native
-       SCF_OP_3AC_POP_RAX,  // pop  rax, only for 3ac & native
+       SCF_OP_3AC_PUSH_RETS, // push return value registers, only for 3ac & native
+       SCF_OP_3AC_POP_RETS,  // pop  return value registers, only for 3ac & native
 
        SCF_OP_3AC_MEMSET,  //
 
index 85ab1d0e66fbb837a538a984110356dc6124c47b..6290c18dfcebee3fc163afc730005c583cb9c45e 100644 (file)
@@ -234,7 +234,9 @@ scf_dn_status_t* scf_dn_status_clone(scf_dn_status_t* ds)
        ds2->active      = ds->active;
        ds2->inited      = ds->inited;
        ds2->updated     = ds->updated;
-       ds2->ret         = ds->ret;
+
+       ds2->ret_flag    = ds->ret_flag;
+       ds2->ret_index   = ds->ret_index;
        return ds2;
 }
 
index 9ca0cdc16dc830e2a279f70d13df50f2485846c4..b58923ff66dd24df2a6ce18e246ab2ae1dfa16eb 100644 (file)
@@ -75,11 +75,13 @@ struct scf_dn_status_s {
 
        intptr_t            color;
 
+       int                 ret_index;
+       uint32_t            ret_flag:1;
+
        uint32_t            active :1;
        uint32_t            inited :1;
        uint32_t            updated:1;
        uint32_t            loaded :1;
-       uint32_t            ret    :1;
 };
 
 scf_dn_index_t*   scf_dn_index_alloc();
index ff2884a020569d60e21c3c65ae4828a759cb0e38..46bf26bc6a6dfe556d06a08bf9328233e2a77f4c 100644 (file)
@@ -224,17 +224,16 @@ int scf_function_same_type(scf_function_t* f0, scf_function_t* f1)
 
 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;
 
-       if (f->signature)
-               scf_string_free(f->signature);
-
-       scf_string_t* s = scf_string_alloc();
+       s = scf_string_alloc();
        if (!s)
                return -ENOMEM;
 
-       scf_type_t*   t = (scf_type_t*)f->node.parent;
        if (t->node.type >= SCF_STRUCT) {
                assert(t->node.class_flag);
 
@@ -247,12 +246,24 @@ int scf_function_signature(scf_function_t* f)
                        goto error;
        }
 
-       ret = scf_string_cat(s, f->node.w->text);
+       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;
        }
@@ -287,6 +298,8 @@ int scf_function_signature(scf_function_t* f)
 
        scf_logd("f signature: %s\n", s->data);
 
+       if (f->signature)
+               scf_string_free(f->signature);
        f->signature = s;
        return 0;
 
index bccf07516f3e8819129d5e169d6e6d4bfb257e73..d6d987c0c328a79f40eb2167a106cc5551d0f188 100644 (file)
@@ -51,7 +51,6 @@ struct scf_function_s {
        int               local_vars_size;
        int               code_bytes;
 
-       uint32_t          vargs_flag  :1;
        uint32_t          visited_flag:1;
        uint32_t          bp_used_flag:1;
 
@@ -59,6 +58,9 @@ struct scf_function_s {
        uint32_t          extern_flag:1;
        uint32_t          inline_flag:1;
        uint32_t          member_flag:1;
+
+       uint32_t          vargs_flag :1;
+       uint32_t          void_flag  :1;
 };
 
 scf_function_t*        scf_function_alloc(scf_lex_word_t* w);
index 7440af442fd1baa9dd6cbc1d2171b275ecff4dd9..8d870b027c7b4954934c6f16e924b29a67ac094c 100644 (file)
@@ -1,84 +1,85 @@
 #include"scf_operator.h"
 #include"scf_core_types.h"
 
-static scf_operator_t  base_operators[] = {
-       {SCF_OP_EXPR,           "(",          0,  1,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_CALL,           "(",          1, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_ARRAY_INDEX,    "[",          1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_POINTER,        "->",         1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_VA_START,       "va_start",   1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_VA_ARG,         "va_arg",     1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_VA_END,         "va_end",     1,  1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_CONTAINER,      "container",  1,  3,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_CREATE,         "create",     2, -1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_TYPE_CAST,      "(",          2,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_LOGIC_NOT,      "!",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_BIT_NOT,        "~",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_NEG,            "-",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_POSITIVE,       "+",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_SIZEOF,         "sizeof",     2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-
-       {SCF_OP_INC,            "++",         2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_DEC,            "--",         2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-
-       {SCF_OP_INC_POST,       "++",         2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_DEC_POST,       "--",         2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-
-       {SCF_OP_DEREFERENCE,    "*",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_ADDRESS_OF,     "&",          2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
-
-       {SCF_OP_MUL,            "*",          4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_DIV,            "/",          4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_MOD,            "%",          4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_ADD,            "+",          5,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_SUB,            "-",          5,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_SHL,            "<<",         6,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_SHR,            ">>",         6,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_BIT_AND,        "&",          7,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_BIT_OR,         "|",          7,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_EQ,             "==",         8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_NE,             "!=",         8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_GT,             ">",          8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_LT,             "<",          8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_GE,             ">=",         8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_LE,             "<=",         8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_LOGIC_AND,      "&&",         9,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_LOGIC_OR,       "||",         9,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_ASSIGN,         "=",         10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_ADD_ASSIGN,     "+=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_SUB_ASSIGN,     "-=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_MUL_ASSIGN,     "*=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_DIV_ASSIGN,     "/=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_MOD_ASSIGN,     "%=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_SHL_ASSIGN,     "<<=",       10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_SHR_ASSIGN,     ">>=",       10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_AND_ASSIGN,     "&=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-       {SCF_OP_OR_ASSIGN,      "|=",        10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
-
-       {SCF_OP_BLOCK,          "{}",        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_RETURN,         "return",    15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_BREAK,          "break",     15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_CONTINUE,       "continue",  15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_GOTO,           "goto",      15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_LABEL,             "label",     15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_IF,             "if",        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_WHILE,          "while",     15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_DO,             "do",        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_FOR,            "for",       15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-
-       {SCF_OP_SWITCH,         "switch",    15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_CASE,           "case",      15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
-       {SCF_OP_DEFAULT,        "default",   15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+static scf_operator_t  base_operators[] =
+{
+       {"(",         NULL,   SCF_OP_EXPR,          0,  1,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"(",         NULL,   SCF_OP_CALL,          1, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"[",         "i",    SCF_OP_ARRAY_INDEX,   1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"->",        "p",    SCF_OP_POINTER,       1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"va_start",  NULL,   SCF_OP_VA_START,      1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"va_arg",    NULL,   SCF_OP_VA_ARG,        1,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"va_end",    NULL,   SCF_OP_VA_END,        1,  1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"container", NULL,   SCF_OP_CONTAINER,     1,  3,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"create",    NULL,   SCF_OP_CREATE,        2, -1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"(",         NULL,   SCF_OP_TYPE_CAST,     2,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"!",         "not",  SCF_OP_LOGIC_NOT,     2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"~",         "bnot", SCF_OP_BIT_NOT,       2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"-",         "neg",  SCF_OP_NEG,           2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"+",         "pos",  SCF_OP_POSITIVE,      2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"sizeof",    NULL,   SCF_OP_SIZEOF,        2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+
+       {"++",        "inc",  SCF_OP_INC,           2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"--",        "dec",  SCF_OP_DEC,           2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+
+       {"++",        "inc",  SCF_OP_INC_POST,      2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"--",        "dec",  SCF_OP_DEC_POST,      2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+
+       {"*",         NULL,   SCF_OP_DEREFERENCE,   2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"&",         NULL,   SCF_OP_ADDRESS_OF,    2,  1,  SCF_OP_ASSOCIATIVITY_RIGHT},
+
+       {"*",         "mul",  SCF_OP_MUL,           4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"/",         "div",  SCF_OP_DIV,           4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"%",         "mod",  SCF_OP_MOD,           4,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"+",         "add",  SCF_OP_ADD,           5,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"-",         "sub",  SCF_OP_SUB,           5,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"<<",         NULL,  SCF_OP_SHL,           6,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {">>",         NULL,  SCF_OP_SHR,           6,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"&",         "band", SCF_OP_BIT_AND,       7,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"|",         "bor",  SCF_OP_BIT_OR,        7,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"==",        "eq",   SCF_OP_EQ,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"!=",        "ne",   SCF_OP_NE,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {">",         "gt",   SCF_OP_GT,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"<",         "lt",   SCF_OP_LT,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {">=",        "ge",   SCF_OP_GE,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"<=",        "le",   SCF_OP_LE,            8,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"&&",        NULL,   SCF_OP_LOGIC_AND,     9,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"||",        NULL,   SCF_OP_LOGIC_OR,      9,  2,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"=",         "a",    SCF_OP_ASSIGN,       10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"+=",        "add_", SCF_OP_ADD_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"-=",        "sub_", SCF_OP_SUB_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"*=",        "mul_", SCF_OP_MUL_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"/=",        "div_", SCF_OP_DIV_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"%=",        "mod_", SCF_OP_MOD_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"<<=",        NULL,  SCF_OP_SHL_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {">>=",        NULL,  SCF_OP_SHR_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"&=",        "and_", SCF_OP_AND_ASSIGN,   10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+       {"|=",        "or_",  SCF_OP_OR_ASSIGN,    10,  2,  SCF_OP_ASSOCIATIVITY_RIGHT},
+
+       {"{}",         NULL,  SCF_OP_BLOCK,        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"return",     NULL,  SCF_OP_RETURN,       15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"break",      NULL,  SCF_OP_BREAK,        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"continue",   NULL,  SCF_OP_CONTINUE,     15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"goto",       NULL,  SCF_OP_GOTO,         15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"label",      NULL,  SCF_LABEL,           15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"if",         NULL,  SCF_OP_IF,           15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"while",      NULL,  SCF_OP_WHILE,        15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"do",         NULL,  SCF_OP_DO,           15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"for",        NULL,  SCF_OP_FOR,          15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+
+       {"switch",     NULL,  SCF_OP_SWITCH,       15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"case",       NULL,  SCF_OP_CASE,         15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
+       {"default",    NULL,  SCF_OP_DEFAULT,      15, -1,  SCF_OP_ASSOCIATIVITY_LEFT},
 };
 
 scf_operator_t* scf_find_base_operator(const char* name, const int nb_operands)
index 88159e4646f0f9735135709ec6f5ac813649cd1d..ab8ddca1dd30b8f697fd2bf9794fe5d6d1193c36 100644 (file)
@@ -9,12 +9,13 @@
 
 struct scf_operator_s
 {
-       int                                             type;
-       char*                                   name;
+       char*  name;
+       char*  signature;
+       int    type;
 
-       int                                             priority;
-       int                                             nb_operands;
-       int                                             associativity;
+       int    priority;
+       int    nb_operands;
+       int    associativity;
 };
 
 scf_operator_t* scf_find_base_operator(const char* name, const int nb_operands);
@@ -22,4 +23,3 @@ scf_operator_t* scf_find_base_operator(const char* name, const int nb_operands);
 scf_operator_t* scf_find_base_operator_by_type(const int type);
 
 #endif
-
index c0b6cd2603f5f748fff30dea7d4fbba470719df5..5ea1bf89d8e33ecdc34e499694655b0ad2463274 100644 (file)
@@ -3,6 +3,8 @@
 
 #include"scf_auto_gc_3ac.c"
 
+int __auto_gc_ds_for_assign(scf_dn_status_t** ds, scf_dag_node_t** dn, scf_3ac_code_t* c);
+
 static int _find_ds_malloced(scf_basic_block_t* bb, void* data)
 {
        scf_dn_status_t* ds = data;
@@ -30,6 +32,9 @@ static int _find_dn_active(scf_basic_block_t* bb, void* data)
        if (scf_vector_find(bb->dn_reloads, data))
                return 1;
 
+       if (scf_vector_find(bb->entry_dn_actives, data))
+               return 1;
+
        scf_logd("bb: %p, dn: %s, 0\n", bb, dn->var->w->text->data);
        return 0;
 }
@@ -97,8 +102,8 @@ static int _bb_add_active(scf_basic_block_t* bb, scf_dag_node_t* dn)
 
        if (scf_type_is_operator(dn->type))
                ret = scf_vector_add(bb->dn_reloads, dn);
-       else
-               ret = scf_vector_add(bb->dn_loads, dn);
+//     else
+//             ret = scf_vector_add(bb->dn_loads, dn);
 
        return ret;
 }
@@ -186,19 +191,25 @@ static int _bb_split_prev_add_free(scf_ast_t* ast, scf_function_t* f, scf_basic_
                return -ENOMEM;
        }
 
+       scf_vector_free(bb1->prevs);
+       bb1->prevs     = bb_split_prevs;
+       bb_split_prevs = NULL;
+
        bb1->ds_auto_gc = scf_dn_status_clone(ds);
-       if (!bb1->ds_auto_gc)
+       if (!bb1->ds_auto_gc) {
+               scf_basic_block_free(bb1);
                return -ENOMEM;
+       }
+
+       int ret = scf_vector_add(bb1->nexts, bb);
+       if (ret < 0) {
+               scf_basic_block_free(bb1);
+               return ret;
+       }
 
        bb1->call_flag      = 1;
        bb1->auto_free_flag = 1;
 
-       scf_vector_add( bb1->nexts, bb);
-       scf_vector_free(bb1->prevs);
-
-       bb1->prevs     = bb_split_prevs;
-       bb_split_prevs = NULL;
-
        scf_list_add_tail(&bb->list, &bb1->list);
 
        scf_3ac_operand_t* dst;
@@ -285,13 +296,13 @@ static int _bb_split_prev_add_free(scf_ast_t* ast, scf_function_t* f, scf_basic_
                        if (!ds3)
                                return -ENOMEM;
 
-                       int ret = scf_vector_add(bb1->ds_malloced, ds3);
+                       ret = scf_vector_add(bb1->ds_malloced, ds3);
                        if (ret < 0)
                                return ret;
                }
        }
 
-       int ret = _bb_add_gc_code_freep(&f->dag_list_head, ast, bb1, ds);
+       ret = _bb_add_gc_code_freep(&f->dag_list_head, ast, bb1, ds);
        if (ret < 0)
                return ret;
 
@@ -323,17 +334,67 @@ static int _bb_split_prevs(scf_basic_block_t* bb, scf_dn_status_t* ds, scf_vecto
        return 0;
 }
 
+static int _bb_add_last_free(scf_dn_status_t* ds, scf_basic_block_t* bb, scf_ast_t* ast, scf_function_t* f)
+{
+       scf_vector_t* vec = scf_vector_alloc();
+       if (!vec)
+               return -ENOMEM;
+
+       scf_basic_block_t* bb2;
+       int j;
+       int dfo = 0;
+
+       int ret = _bb_find_ds_malloced(bb, &f->basic_block_list_head, ds, vec);
+       if (ret < 0) {
+               scf_vector_free(vec);
+               return ret;
+       }
+
+#define AUTO_GC_FIND_MAX_DFO() \
+       do { \
+               for (j  = 0; j < vec->size; j++) { \
+                       bb2 =        vec->data[j]; \
+                       \
+                       if (bb2->dfo > dfo) \
+                       dfo = bb2->dfo; \
+               } \
+       } while (0)
+       AUTO_GC_FIND_MAX_DFO();
+       vec->size = 0;
+
+       ret = _bb_find_dn_active(bb, &f->basic_block_list_head, ds->dag_node, vec);
+       if (ret < 0) {
+               scf_vector_free(vec);
+               return ret;
+       }
+       AUTO_GC_FIND_MAX_DFO();
+       vec->size = 0;
+
+       for (j = 0; j < bb->dominators->size; j++) {
+               bb2       = bb->dominators->data[j];
+
+               if (bb2->dfo > dfo)
+                       break;
+       }
+
+       ret = _bb_split_prevs(bb2, ds, vec);
+       if (ret < 0) {
+               scf_vector_free(vec);
+               return ret;
+       }
+
+       return _bb_split_prev_add_free(ast, f, bb2, ds, vec);
+}
+
 static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
 {
-       scf_list_t*        bb_list_head = &f->basic_block_list_head;
-       scf_list_t*        l;
+       scf_list_t*        l = scf_list_tail(&f->basic_block_list_head);
        scf_basic_block_t* bb;
        scf_dn_status_t*   ds;
        scf_dag_node_t*    dn;
        scf_variable_t*    v;
        scf_vector_t*      local_arrays;
 
-       l  = scf_list_tail(bb_list_head);
        bb = scf_list_data(l, scf_basic_block_t, list);
 
        scf_logd("bb: %p, bb->ds_malloced->size: %d\n", bb, bb->ds_malloced->size);
@@ -344,27 +405,23 @@ static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
 
        int ret;
        int i;
-       for (i = 0; i < bb->ds_malloced->size; ) {
+
+       for (i = 0; i < bb->ds_malloced->size; i++) {
                ds =        bb->ds_malloced->data[i];
 
                dn = ds->dag_node;
                v  = dn->var;
 
-               scf_logw("f: %s, last free: v_%d_%d/%s, ds->ret: %u\n",
-                               f->node.w->text->data, v->w->line, v->w->pos, v->w->text->data, ds->ret);
+               scf_logw("%s(), last free: v_%d_%d/%s, ds->ret_flag: %u\n",
+                               f->node.w->text->data, v->w->line, v->w->pos, v->w->text->data, ds->ret_flag);
                scf_dn_status_print(ds);
 
-               if (ds->ret) {
-                       i++;
+               if (ds->ret_flag)
                        continue;
-               }
 
                if (ds->dn_indexes) {
-
-                       scf_dn_index_t*  di;
-
-                       int var_index = 0;
                        int j;
+                       scf_dn_index_t* di;
 
                        for (j = ds->dn_indexes->size - 1; j >= 0; j--) {
                                di = ds->dn_indexes->data[j];
@@ -374,81 +431,24 @@ static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
                                        break;
                                }
 
-                               if (-1 == di->index)
-                                       var_index++;
-                       }
-
-                       if (var_index > 0) {
-                               if (v->nb_dimentions > 0 && v->local_flag) {
+                               if (-1 == di->index) {
+                                       if (v->nb_dimentions > 0 && v->local_flag) {
 
-                                       if (scf_vector_add_unique(local_arrays, dn) < 0)
-                                               return -ENOMEM;
+                                               ret = scf_vector_add_unique(local_arrays, dn);
+                                               if (ret < 0)
+                                                       goto error;
+                                       }
+                                       break;
                                }
-
-                               i++;
-                               continue;
                        }
 
-                       if (j >= 0) {
-                               i++;
+                       if (j >= 0)
                                continue;
-                       }
-               }
-
-               scf_vector_t* vec = scf_vector_alloc();
-               if (!vec)
-                       return -ENOMEM;
-
-               scf_basic_block_t* bb1;
-               scf_basic_block_t* bb_dominator;
-
-               int dfo = 0;
-               int j;
-
-               ret = _bb_find_ds_malloced(bb, bb_list_head, ds, vec);
-               if (ret < 0) {
-                       scf_vector_free(vec);
-                       return ret;
-               }
-#define AUTO_GC_FIND_MAX_DFO() \
-               do { \
-                       for (j  = 0; j < vec->size; j++) { \
-                               bb1 =        vec->data[j]; \
-                               \
-                               if (bb1->dfo > dfo) \
-                                       dfo = bb1->dfo; \
-                       } \
-               } while (0)
-               AUTO_GC_FIND_MAX_DFO();
-
-               vec->size = 0;
-
-               ret = _bb_find_dn_active(bb, bb_list_head, dn, vec);
-               if (ret < 0) {
-                       scf_vector_free(vec);
-                       return ret;
-               }
-               AUTO_GC_FIND_MAX_DFO();
-
-               for (j = 0; j    < bb->dominators->size; j++) {
-                       bb_dominator = bb->dominators->data[j];
-
-                       if (bb_dominator->dfo > dfo)
-                               break;
-               }
-
-               vec->size = 0;
-
-               ret = _bb_split_prevs(bb_dominator, ds, vec);
-               if (ret < 0) {
-                       scf_vector_free(vec);
-                       return ret;
                }
 
-               ret = _bb_split_prev_add_free(ast, f, bb_dominator, ds, vec);
+               ret = _bb_add_last_free(ds, bb, ast, f);
                if (ret < 0)
-                       return ret;
-               i++;
+                       goto error;
        }
 
        for (i = 0; i < local_arrays->size; i++) {
@@ -456,14 +456,17 @@ static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
 
                ret = _bb_add_memset_array(ast, f, dn);
                if (ret < 0)
-                       return ret;
+                       goto error;
 
                ret = _bb_add_free_arry(ast, f, bb, dn);
                if (ret < 0)
-                       return ret;
+                       goto error;
        }
 
-       return 0;
+       ret = 0;
+error:
+       scf_vector_free(local_arrays);
+       return ret;
 }
 
 #define AUTO_GC_BB_SPLIT(parent, child) \
@@ -486,19 +489,29 @@ static int _auto_gc_last_free(scf_ast_t* ast, scf_function_t* f)
                scf_list_add_front(&parent->list, &child->list); \
        } while (0)
 
-static int _optimize_auto_gc_bb_ref(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t** pbb, scf_list_t* bb_list_head, scf_dn_status_t* ds)
+static int _auto_gc_bb_split(scf_basic_block_t* parent, scf_basic_block_t** pchild)
+{
+       scf_basic_block_t* child = NULL;
+
+       AUTO_GC_BB_SPLIT(parent, child);
+
+       *pchild = child;
+       return 0;
+}
+
+static int _auto_gc_bb_ref(scf_dn_status_t* ds_obj, scf_vector_t* ds_malloced, scf_ast_t* ast, scf_function_t* f, scf_basic_block_t** pbb)
 {
        scf_basic_block_t* cur_bb = *pbb;
        scf_basic_block_t* bb1    = NULL;
-       scf_dag_node_t*    dn     = ds->dag_node;
+       scf_dag_node_t*    dn     = ds_obj->dag_node;
 
        AUTO_GC_BB_SPLIT(cur_bb, bb1);
 
-       bb1->ds_auto_gc = scf_dn_status_clone(ds);
+       bb1->ds_auto_gc = scf_dn_status_clone(ds_obj);
        if (!bb1->ds_auto_gc)
                return -ENOMEM;
 
-       int ret = _bb_add_gc_code_ref(&f->dag_list_head, ast, bb1, ds);
+       int ret = _bb_add_gc_code_ref(&f->dag_list_head, ast, bb1, ds_obj);
        if (ret < 0)
                return ret;
 
@@ -510,6 +523,14 @@ static int _optimize_auto_gc_bb_ref(scf_ast_t* ast, scf_function_t* f, scf_basic
        if (ret < 0)
                return ret;
 
+       if (!scf_vector_find_cmp(ds_malloced, ds_obj, scf_ds_cmp_like_indexes)) {
+               ret = scf_vector_add(ds_malloced, ds_obj);
+               if (ret < 0)
+                       return ret;
+
+               scf_dn_status_ref(ds_obj);
+       }
+
        bb1->call_flag  = 1;
        bb1->dereference_flag = 0;
        bb1->auto_ref_flag    = 1;
@@ -518,7 +539,7 @@ static int _optimize_auto_gc_bb_ref(scf_ast_t* ast, scf_function_t* f, scf_basic
        return 0;
 }
 
-static int _optimize_auto_gc_bb_free(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t** pbb, scf_dn_status_t* ds)
+static int _bb_split_add_free(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t** pbb, scf_dn_status_t* ds)
 {
        scf_basic_block_t* cur_bb = *pbb;
        scf_basic_block_t* bb1    = NULL;
@@ -589,44 +610,51 @@ static int _bb_prevs_malloced(scf_basic_block_t* bb, scf_vector_t* ds_malloced)
 
 int __bb_find_ds_alias(scf_vector_t* aliases, scf_dn_status_t* ds_obj, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head);
 
-static int _bb_need_ref(scf_dn_status_t* ds_obj, scf_vector_t* ds_malloced,
-               scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+static int _bb_need_ref(scf_dag_node_t* dn, scf_vector_t* ds_malloced, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_list_t* bb_list_head)
 {
-       scf_dn_status_t* ds_alias;
+       scf_dn_status_t* ds = NULL;
        scf_vector_t*    aliases;
-
-       int ret;
        int i;
 
+       int ret = scf_ds_for_dn(&ds, dn);
+       if (ret < 0)
+               return ret;
+
+       if (scf_vector_find_cmp(ds_malloced, ds, scf_ds_cmp_like_indexes)) {
+               scf_dn_status_free(ds);
+               return 1;
+       }
+
        aliases = scf_vector_alloc();
-       if (!aliases)
+       if (!aliases) {
+               scf_dn_status_free(ds);
                return -ENOMEM;
+       }
 
-       ret = __bb_find_ds_alias(aliases, ds_obj, c, bb, bb_list_head);
-       if (ret < 0)
-               return ret;
+       ret = __bb_find_ds_alias(aliases, ds, c, bb, bb_list_head);
 
-       scf_logd("aliases->size: %d\n", aliases->size);
+       scf_dn_status_free(ds);
+       ds = NULL;
+       if (ret < 0)
+               goto error;
 
-       int need = 0;
+       ret = 0;
        for (i = 0; i < aliases->size; i++) {
-               ds_alias  = aliases->data[i];
+               ds =        aliases->data[i];
 
-               if (!ds_alias->dag_node)
+               if (!ds->dag_node)
                        continue;
 
-               if (scf_vector_find_cmp(ds_malloced, ds_alias, scf_ds_cmp_like_indexes)) {
-                       need = 1;
+               if (scf_vector_find_cmp(ds_malloced, ds, scf_ds_cmp_like_indexes)) {
+                       ret = 1;
                        break;
                }
        }
 
-       if (scf_vector_find_cmp(ds_malloced, ds_obj, scf_ds_cmp_like_indexes)) {
-               need = 1;
-       }
-
+error:
+       scf_vector_clear(aliases, ( void (*)(void*) )scf_dn_status_free);
        scf_vector_free (aliases);
-       return need;
+       return ret;
 }
 
 static int _bb_split_prevs_need_free(scf_dn_status_t* ds_obj, scf_vector_t* ds_malloced, scf_vector_t* bb_split_prevs, scf_basic_block_t* bb)
@@ -643,168 +671,149 @@ static int _bb_split_prevs_need_free(scf_dn_status_t* ds_obj, scf_vector_t* ds_m
        return 0;
 }
 
-static int _optimize_auto_gc_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+static int _auto_gc_bb_free(scf_dn_status_t* ds_obj, scf_vector_t* ds_malloced, scf_vector_t* ds_assigned, scf_ast_t* ast,
+               scf_function_t*     f,
+               scf_basic_block_t*  bb,
+               scf_basic_block_t** cur_bb)
 {
-       scf_list_t*     l;
-       scf_3ac_code_t* c;
-       scf_vector_t*   ds_malloced;
-       scf_vector_t*   ds_assigned;
-
-       scf_basic_block_t* bb_prev = NULL;
-       scf_basic_block_t* cur_bb  = bb;
-
-       ds_malloced = scf_vector_alloc();
-       if (!ds_malloced)
-               return -ENOMEM;
+       scf_vector_t* bb_split_prevs = scf_vector_alloc();
 
-       ds_assigned = scf_vector_alloc();
-       if (!ds_assigned)
+       if (!bb_split_prevs)
                return -ENOMEM;
 
-       // at first, the malloced vars, are ones malloced in previous blocks
-
-       int ret = _bb_prevs_malloced(bb, ds_malloced);
+       int ret = _bb_split_prevs_need_free(ds_obj, ds_malloced, bb_split_prevs, bb);
        if (ret < 0) {
-               scf_vector_clear(ds_malloced, ( void (*)(void*) )scf_dn_status_free);
-               scf_vector_free(ds_malloced);
+               scf_vector_free(bb_split_prevs);
                return ret;
        }
 
-       for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
+       if (ret) {
+               if (!scf_vector_find_cmp(ds_assigned, ds_obj, scf_ds_cmp_like_indexes)
+                               && bb_split_prevs->size > 0
+                               && bb_split_prevs->size < bb->prevs->size) {
 
-               c  = scf_list_data(l, scf_3ac_code_t, list);
-               l  = scf_list_next(l);
-
-               scf_3ac_operand_t* base;
-               scf_3ac_operand_t* member;
-               scf_3ac_operand_t* index;
-               scf_3ac_operand_t* scale;
+                       return _bb_split_prev_add_free(ast, f, bb, ds_obj, bb_split_prevs);
+               }
 
-               scf_3ac_operand_t* dst;
-               scf_3ac_operand_t* src;
-               scf_dag_node_t*    dn;
-               scf_dn_status_t*   ds_obj;
-               scf_variable_t*    v0;
+               ret = _bb_split_add_free(ast, f, cur_bb, ds_obj);
+       }
 
-               if (SCF_OP_ASSIGN == c->op->type) {
+       scf_vector_free(bb_split_prevs);
+       bb_split_prevs = NULL;
+       return ret;
+}
 
-                       dst = c->dsts->data[0];
-                       v0  = dst->dag_node->var;
+static int _auto_gc_retval(scf_dn_status_t* ds_obj, scf_dag_node_t* dn, scf_vector_t* ds_malloced, scf_3ac_code_t* c, scf_function_t* f)
+{
+       scf_dag_node_t*  pf;
+       scf_function_t*  f2;
+       scf_variable_t*  fret;
+       scf_node_t*      parent;
+       scf_node_t*      result;
 
-                       if (!scf_variable_may_malloced(v0))
-                               goto _end;
+       int i = 0;
 
-                       ds_obj = NULL;
+       if (dn->node->split_flag) {
+               parent = dn->node->split_parent;
 
-                       ret = scf_ds_for_dn(&ds_obj, dst->dag_node);
-                       if (!ds_obj)
-                               return -ENOMEM;
+               assert(SCF_OP_CALL == parent->type || SCF_OP_CREATE == parent->type);
 
-                       src = c->srcs->data[0];
-                       dn  = src->dag_node;
+               for (i = 0; i < parent->result_nodes->size; i++) {
+                       result    = parent->result_nodes->data[i];
 
-               } else if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type) {
+                       if (dn->node == result)
+                               break;
+               }
+       }
 
-                       assert(4 == c->srcs->size);
+       pf   = dn->childs->data[0];
+       f2   = pf->var->func_ptr;
+       fret = f2->rets->data[i];
 
-                       base  = c->srcs->data[0];
-                       index = c->srcs->data[1];
-                       scale = c->srcs->data[2];
-                       src   = c->srcs->data[3];
-                       dn    = src->dag_node;
-                       v0    = _scf_operand_get(base->node->parent);
+       if (!strcmp(f2->node.w->text->data, "scf__auto_malloc") || fret->auto_gc_flag) {
 
-                       if (!scf_variable_may_malloced(v0))
-                               goto _end;
+               assert(SCF_OP_RETURN != c->op->type);
+//             fret = f->rets->data[i];
+//             fret->auto_gc_flag = 1;
 
-                       ds_obj = NULL;
+               if (!scf_vector_find_cmp(ds_malloced, ds_obj, scf_ds_cmp_like_indexes)) {
 
-                       int ret = scf_ds_for_assign_array_member(&ds_obj, base->dag_node, index->dag_node, scale->dag_node);
+                       int ret = scf_vector_add(ds_malloced, ds_obj);
                        if (ret < 0)
                                return ret;
 
-                       if (ds_obj->dag_node->var->arg_flag)
-                               ds_obj->ret = 1;
-
-               } else if (SCF_OP_3AC_ASSIGN_POINTER == c->op->type) {
-
-                       assert(3 == c->srcs->size);
+                       scf_dn_status_ref(ds_obj);
+               }
+       }
 
-                       base   = c->srcs->data[0];
-                       member = c->srcs->data[1];
-                       src    = c->srcs->data[2];
-                       dn     = src->dag_node;
-                       v0     = member->dag_node->var;
+       return 0;
+}
 
-                       if (!scf_variable_may_malloced(v0))
-                               goto _end;
+static int _optimize_auto_gc_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_block_t* bb, scf_list_t* bb_list_head)
+{
+       scf_basic_block_t*  cur_bb = bb;
+       scf_basic_block_t*  bb2;
+       scf_3ac_code_t*     c;
+       scf_vector_t*       ds_malloced;
+       scf_vector_t*       ds_assigned;
+       scf_list_t*         l;
 
-                       ds_obj = NULL;
+       ds_malloced = scf_vector_alloc();
+       if (!ds_malloced)
+               return -ENOMEM;
 
-                       int ret = scf_ds_for_assign_member(&ds_obj, base->dag_node, member->dag_node);
-                       if (ret < 0)
-                               return ret;
+       ds_assigned = scf_vector_alloc();
+       if (!ds_assigned) {
+               scf_vector_free(ds_malloced);
+               return -ENOMEM;
+       }
 
-                       if (ds_obj->dag_node->var->arg_flag)
-                               ds_obj->ret = 1;
+       // at first, the malloced vars, are ones malloced in previous blocks
 
-               } else if (SCF_OP_3AC_ASSIGN_DEREFERENCE == c->op->type) {
+       int ret = _bb_prevs_malloced(bb, ds_malloced);
+       if (ret < 0)
+               goto error;
 
-                       assert(2 == c->srcs->size);
+       for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
 
-                       src = c->srcs->data[1];
-                       dn  = src->dag_node;
-                       v0  = dn->var;
+               c  = scf_list_data(l, scf_3ac_code_t, list);
+               l  = scf_list_next(l);
 
-                       if (!scf_variable_may_malloced(v0))
-                               goto _end;
+               scf_dn_status_t*  ds_obj = NULL;
+               scf_dn_status_t*  ds     = NULL;
+               scf_dag_node_t*   dn     = NULL;
 
-                       src     = c->srcs->data[0];
-                       ds_obj  = NULL;
+               if (SCF_OP_ASSIGN == c->op->type
+                               || SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type
+                               || SCF_OP_3AC_ASSIGN_POINTER == c->op->type
+                               || SCF_OP_3AC_ASSIGN_DEREFERENCE == c->op->type) {
 
-                       int ret = scf_ds_for_assign_dereference(&ds_obj, src->dag_node);
+                       ret = __auto_gc_ds_for_assign(&ds_obj, &dn, c);
                        if (ret < 0)
-                               return ret;
+                               goto error;
 
-               } else
-                       goto _end;
-
-               scf_vector_t* bb_split_prevs = scf_vector_alloc();
-               if (!bb_split_prevs)
-                       return -ENOMEM;
-
-               ret = _bb_split_prevs_need_free(ds_obj, ds_malloced, bb_split_prevs, bb);
-               if (ret < 0) {
-                       scf_loge("\n");
-                       return ret;
-               }
-
-               if (ret) {
-                       if (!scf_vector_find_cmp(ds_assigned, ds_obj, scf_ds_cmp_like_indexes)
-                                       && bb_split_prevs->size > 0
-                                       && bb_split_prevs->size < bb->prevs->size)
-
-                               ret = _bb_split_prev_add_free(ast, f, bb, ds_obj, bb_split_prevs);
-                       else {
-                               scf_vector_free(bb_split_prevs);
-                               bb_split_prevs = NULL;
+                       if (!ds_obj)
+                               goto end;
 
-                               ret = _optimize_auto_gc_bb_free(ast, f, &cur_bb, ds_obj);
+                       if (SCF_OP_ASSIGN != c->op->type) {
+                               if (ds_obj->dag_node->var->arg_flag)
+                                       ds_obj->ret_flag = 1;
                        }
+               } else
+                       goto end;
 
-                       if (ret < 0)
-                               return ret;
-               } else {
-                       scf_vector_free(bb_split_prevs);
-                       bb_split_prevs = NULL;
+               ret = _auto_gc_bb_free(ds_obj, ds_malloced, ds_assigned, ast, f, bb, &cur_bb);
+               if (ret < 0) {
+                       scf_dn_status_free(ds_obj);
+                       goto error;
                }
 
-               if (scf_vector_add(ds_assigned, ds_obj) < 0) {
+               ret = scf_vector_add(ds_assigned, ds_obj);
+               if (ret < 0) {
                        scf_dn_status_free(ds_obj);
-                       return -ENOMEM;
+                       goto error;
                }
-
-_ref:
+ref:
                if (!dn->var->local_flag && cur_bb != bb)
                        dn ->var->tmp_flag = 1;
 
@@ -820,100 +829,54 @@ _ref:
 
                if (SCF_OP_CALL == dn->type || dn->node->split_flag) {
 
-                       if (dn->node->split_flag) {
-                               assert(SCF_OP_CALL   == dn->node->split_parent->type
-                                       || SCF_OP_CREATE == dn->node->split_parent->type);
-                       }
-
-                       scf_dag_node_t* dn_pf;
-                       scf_function_t* f2;
-                       scf_variable_t* ret;
-
-                       dn_pf = dn->childs->data[0];
-                       f2    = dn_pf->var->func_ptr;
-                       ret   = f2->rets->data[0];
-
-                       if (!strcmp(f2->node.w->text->data, "scf__auto_malloc") || ret->auto_gc_flag) {
-
-                               if (SCF_OP_RETURN == c->op->type) {
-                                       ret = f->rets->data[0];
-                                       ret->auto_gc_flag = 1;
-                               }
-
-                               if (!scf_vector_find_cmp(ds_malloced, ds_obj, scf_ds_cmp_like_indexes)) {
-
-                                       assert(0 == scf_vector_add(ds_malloced, ds_obj));
-                               } else {
-                                       scf_dn_status_free(ds_obj);
-                                       ds_obj = NULL;
-                               }
-
-                               if (cur_bb != bb) {
-                                       scf_list_del(&c->list);
-                                       scf_list_add_tail(&cur_bb->code_list_head, &c->list);
-                               }
-                               continue;
-                       }
-               } else {
-                       scf_dn_status_t* ds = NULL;
-
-                       ret = scf_ds_for_dn(&ds, dn);
+                       ret = _auto_gc_retval(ds_obj, dn, ds_malloced, c, f);
                        if (ret < 0)
-                               return ret;
-
-                       int ret = _bb_need_ref(ds, ds_malloced, c, bb, bb_list_head);
-
-                       scf_dn_status_free(ds);
-                       ds = NULL;
+                               goto error;
 
+               } else {
+                       ret = _bb_need_ref(dn, ds_malloced, c, bb, bb_list_head);
                        if (ret < 0)
-                               return ret;
+                               goto error;
 
                        if (ret > 0) {
-                               scf_basic_block_t* bb2 = NULL;
-
-                               if (SCF_OP_RETURN == c->op->type) {
-                                       scf_variable_t* ret = f->rets->data[0];
-                                       ret->auto_gc_flag = 1;
-                               }
+                               assert(SCF_OP_RETURN != c->op->type);
+//                             scf_variable_t* fret = f->rets->data[0];
+//                             fret->auto_gc_flag = 1;
 
                                if (cur_bb != bb) {
                                        scf_list_del(&c->list);
                                        scf_list_add_tail(&cur_bb->code_list_head, &c->list);
                                }
 
-                               int ret = _optimize_auto_gc_bb_ref(ast, f, &cur_bb, bb_list_head, ds_obj);
+                               ret = _auto_gc_bb_ref(ds_obj, ds_malloced, ast, f, &cur_bb);
                                if (ret < 0)
-                                       return ret;
-
-                               if (!scf_vector_find_cmp(ds_malloced, ds_obj, scf_ds_cmp_like_indexes)) {
-
-                                       assert(0 == scf_vector_add(ds_malloced, ds_obj));
-                               } else {
-                                       scf_dn_status_free(ds_obj);
-                                       ds_obj = NULL;
-                               }
+                                       goto error;
 
                                if (l != scf_list_sentinel(&bb->code_list_head)) {
+                                       bb2 = NULL;
+                                       ret = _auto_gc_bb_split(cur_bb, &bb2);
+                                       if (ret < 0)
+                                               goto error;
 
-                                       AUTO_GC_BB_SPLIT(cur_bb, bb2);
                                        cur_bb = bb2;
                                }
-
                                continue;
                        }
                }
-
-               scf_dn_status_free(ds_obj);
-               ds_obj = NULL;
-_end:
+end:
                if (cur_bb != bb) {
                        scf_list_del(&c->list);
                        scf_list_add_tail(&cur_bb->code_list_head, &c->list);
                }
        }
 
-       return 0;
+       ret = 0;
+error:
+       scf_vector_clear(ds_assigned, ( void (*)(void*) )scf_dn_status_free);
+       scf_vector_clear(ds_malloced, ( void (*)(void*) )scf_dn_status_free);
+       scf_vector_free (ds_assigned);
+       scf_vector_free (ds_malloced);
+       return ret;
 }
 
 static int _optimize_auto_gc(scf_ast_t* ast, scf_function_t* f, scf_vector_t* functions)
index 549f261b01ba58e197ccbc439cb0eff91a889d89..6e0bf9b2d1099d1a674143ec995f5a69bae46ead 100644 (file)
@@ -33,7 +33,8 @@ static int _bb_add_ds(scf_basic_block_t* bb, scf_dn_status_t* ds_obj)
                }
        }
 
-       ds->ret |= ds_obj->ret;
+       ds->ret_flag |= ds_obj->ret_flag;
+       ds->ret_index = ds_obj->ret_index;
        return 0;
 }
 
@@ -236,7 +237,7 @@ static int _bb_add_ds_for_ret(scf_basic_block_t* bb, scf_dn_status_t* ds_obj, sc
        for (i  = 0; i < bb2->ds_malloced->size; i++) {
                ds2 =        bb2->ds_malloced->data[i];
 
-               if (!ds2->ret)
+               if (!ds2->ret_flag)
                        continue;
 
                __bb_add_ds_append(bb, ds_obj, bb2, ds2);
@@ -320,9 +321,9 @@ static int _auto_gc_find_argv_out(scf_basic_block_t* cur_bb, scf_3ac_code_t* c)
                        return ret;
 
                if (ds_obj->dag_node->var->arg_flag)
-                       ds_obj->ret = 1;
+                       ds_obj->ret_flag = 1;
 
-               ret = scf_vector_add_unique(cur_bb->dn_reloads, ds_obj->dag_node);
+               ret = scf_vector_add_unique(cur_bb->entry_dn_actives, ds_obj->dag_node);
                if (ret < 0) {
                        scf_dn_status_free(ds_obj);
                        return ret;
@@ -348,31 +349,40 @@ static int _auto_gc_find_ret(scf_basic_block_t* cur_bb, scf_3ac_code_t* c)
        scf_3ac_operand_t* dst;
        scf_3ac_operand_t* src = c->srcs->data[0];
        scf_function_t*    f2  = src->dag_node->var->func_ptr;
-       scf_variable_t*    ret = f2->rets->data[0];
+       scf_variable_t*    fret;
        scf_variable_t*    v;
        scf_dn_status_t*   ds_obj;
 
-       if (ret->auto_gc_flag) {
-               dst = c->dsts->data[0];
-               v   = dst->dag_node->var;
+       assert(c->dsts->size <= f2->rets->size);
 
-               if (!scf_variable_may_malloced(v))
-                       return 0;
+       int i;
+       for (i = 0; i < c->dsts->size; i++) {
+               dst       = c->dsts->data[i];
 
-               ds_obj = scf_dn_status_alloc(dst->dag_node);
-               if (!ds_obj)
-                       return -ENOMEM;
+               fret = f2->rets->data[i];
+               v    = dst->dag_node->var;
 
-               _bb_add_ds(cur_bb, ds_obj);
+               scf_logd("--- f2: %s(), i: %d, auto_gc_flag: %d\n", f2->node.w->text->data, i, fret->auto_gc_flag);
 
-               scf_dn_status_free(ds_obj);
-               ds_obj = NULL;
+               if (fret->auto_gc_flag) {
+                       if (!scf_variable_may_malloced(v))
+                               return 0;
+
+                       ds_obj = scf_dn_status_alloc(dst->dag_node);
+                       if (!ds_obj)
+                               return -ENOMEM;
+
+                       _bb_add_ds(cur_bb, ds_obj);
+
+                       scf_dn_status_free(ds_obj);
+                       ds_obj = NULL;
+               }
        }
 
        return 0;
 }
 
-static int __auto_gc_ds_for_assign(scf_dn_status_t** ds, scf_dag_node_t** dn, scf_3ac_code_t* c)
+int __auto_gc_ds_for_assign(scf_dn_status_t** ds, scf_dag_node_t** dn, scf_3ac_code_t* c)
 {
        scf_3ac_operand_t* base;
        scf_3ac_operand_t* member;
@@ -451,6 +461,145 @@ static int __auto_gc_ds_for_assign(scf_dn_status_t** ds, scf_dag_node_t** dn, sc
        return 0;
 }
 
+static int _auto_gc_find_ref(scf_dn_status_t* ds_obj, scf_dag_node_t* dn, scf_3ac_code_t* c,
+               scf_basic_block_t* bb,
+               scf_basic_block_t* cur_bb,
+               scf_function_t*    f)
+{
+       scf_dn_status_t*  ds;
+       scf_dag_node_t*   pf;
+       scf_function_t*   f2;
+       scf_variable_t*   fret;
+       scf_node_t*       parent;
+       scf_node_t*       result;
+
+       if (SCF_OP_CALL == dn->type || dn->node->split_flag) {
+               int i = 0;
+
+               if (dn->node->split_flag) {
+                       parent = dn->node->split_parent;
+
+                       assert(SCF_OP_CALL == parent->type || SCF_OP_CREATE == parent->type);
+
+                       for (i = 0; i < parent->result_nodes->size; i++) {
+                               result    = parent->result_nodes->data[i];
+
+                               if (dn->node == result)
+                                       break;
+                       }
+               }
+
+               pf   = dn->childs->data[0];
+               f2   = pf->var->func_ptr;
+               fret = f2->rets->data[i];
+
+               scf_logd("f2: %s, rets[%d], auto_gc_flag: %d\n", f2->node.w->text->data, i, fret->auto_gc_flag);
+
+               if (!strcmp(f2->node.w->text->data, "scf__auto_malloc")) {
+                       _bb_add_ds(cur_bb, ds_obj);
+                       return 1;
+               }
+
+               if (fret->auto_gc_flag) {
+                       _bb_add_ds        (cur_bb, ds_obj);
+                       _bb_add_ds_for_ret(cur_bb, ds_obj, f2);
+
+                       ds = scf_dn_status_alloc(dn);
+                       if (!ds)
+                               return -ENOMEM;
+
+                       _bb_del_ds(cur_bb, ds);
+
+                       scf_dn_status_free(ds);
+                       ds = NULL;
+                       return 2;
+               }
+       } else {
+               ds  = NULL;
+               int ret = scf_ds_for_dn(&ds, dn);
+               if (ret < 0)
+                       return ret;
+
+               ret = _bb_find_ds_alias(ds, c, bb, &f->basic_block_list_head);
+
+               scf_dn_status_free(ds);
+               ds = NULL;
+               if (ret < 0)
+                       return ret;
+
+               if (1 == ret) {
+                       _bb_add_ds(cur_bb, ds_obj);
+                       return 2;
+               }
+       }
+
+       return 0;
+}
+
+static int _auto_gc_find_return(scf_vector_t* objs, scf_3ac_code_t* c, scf_basic_block_t* bb, scf_basic_block_t* cur_bb, scf_function_t* f)
+{
+       scf_3ac_operand_t* src;
+       scf_dn_status_t*   ds_obj;
+       scf_dag_node_t*    dn;
+       scf_variable_t*    v;
+
+       int count = 0;
+       int i;
+
+       for (i  = 0; i < c->srcs->size; i++) {
+               src =        c->srcs->data[i];
+
+               dn  = src->dag_node;
+               v   = dn->var;
+
+               if (!scf_variable_may_malloced(dn->var))
+                       continue;
+
+               if (v->w)
+                       scf_logd("v: %s, line: %d\n", v->w->text->data, v->w->line);
+
+               while (dn) {
+                       if (SCF_OP_TYPE_CAST == dn->type)
+                               dn = dn->childs->data[0];
+
+                       else if (SCF_OP_EXPR == dn->type)
+                               dn = dn->childs->data[0];
+                       else
+                               break;
+               }
+
+               ds_obj = scf_dn_status_alloc(dn);
+               if (!ds_obj)
+                       return -ENOMEM;
+
+               ds_obj->ret_flag  = 1;
+               ds_obj->ret_index = i;
+
+               scf_logd("i: %d, ds: %#lx, ret_index: %d\n", i, 0xffffff &(uintptr_t)ds_obj, ds_obj->ret_index);
+//             scf_dn_status_print(ds_obj);
+
+               int ret = _auto_gc_find_ref(ds_obj, dn, c, bb, cur_bb, f);
+               if (ret < 0) {
+                       scf_dn_status_free(ds_obj);
+                       return ret;
+               }
+
+               count += ret > 0;
+
+               if (ret > 1) {
+                       ret = scf_vector_add(objs, ds_obj);
+                       if (ret < 0) {
+                               scf_dn_status_free(ds_obj);
+                               return ret;
+                       }
+               } else
+                       scf_dn_status_free(ds_obj);
+               ds_obj = NULL;
+       }
+
+       return count;
+}
+
 static int _auto_gc_bb_find(scf_basic_block_t* bb, scf_function_t* f)
 {
        scf_basic_block_t* cur_bb = bb;
@@ -460,6 +609,7 @@ static int _auto_gc_bb_find(scf_basic_block_t* bb, scf_function_t* f)
 
        int count = 0;
        int ret;
+       int i;
 
        for (l = scf_list_head(&bb->code_list_head); l != scf_list_sentinel(&bb->code_list_head); ) {
 
@@ -485,23 +635,49 @@ static int _auto_gc_bb_find(scf_basic_block_t* bb, scf_function_t* f)
 
                        if (SCF_OP_ASSIGN != c->op->type) {
                                if (ds_obj->dag_node->var->arg_flag)
-                                       ds_obj->ret = 1;
+                                       ds_obj->ret_flag = 1;
                        }
-#if 1
-               } else if (SCF_OP_RETURN == c->op->type) {
-                       src = c->srcs->data[0];
-                       dn  = src->dag_node;
 
-                       if (!scf_variable_may_malloced(dn->var))
-                               goto end;
+               } else if (SCF_OP_RETURN == c->op->type) {
 
-                       ds_obj = scf_dn_status_alloc(dn);
-                       if (!ds_obj)
+                       scf_vector_t* objs = scf_vector_alloc();
+                       if (!objs)
                                return -ENOMEM;
 
-                       ds_obj->ret = 1;
-                       goto ref;
-#endif
+                       ret = _auto_gc_find_return(objs, c, bb, cur_bb, f);
+                       if (ret < 0) {
+                               scf_vector_clear(objs, ( void (*)(void*) )scf_dn_status_free);
+                               scf_vector_free (objs);
+                               return ret;
+                       }
+                       count += ret;
+
+                       if (cur_bb != bb) {
+                               scf_list_del(&c->list);
+                               scf_list_add_tail(&cur_bb->code_list_head, &c->list);
+                       }
+
+                       if (objs->size > 0 && l != scf_list_sentinel(&bb->code_list_head)) {
+
+                               AUTO_GC_FIND_BB_SPLIT(cur_bb, bb2);
+                               cur_bb = bb2;
+
+                               for (i = 0; i < objs->size; i++) {
+                                       ds_obj    = objs->data[i];
+
+                                       ret = scf_vector_add_unique(cur_bb->entry_dn_actives, ds_obj->dag_node);
+                                       if (ret < 0) {
+                                               scf_vector_clear(objs, ( void (*)(void*) )scf_dn_status_free);
+                                               scf_vector_free (objs);
+                                               return ret;
+                                       }
+                               }
+                       }
+
+                       scf_vector_clear(objs, ( void (*)(void*) )scf_dn_status_free);
+                       scf_vector_free (objs);
+                       continue;
+
                } else if (SCF_OP_CALL == c->op->type) {
                        assert(c->srcs->size > 0);
 
@@ -524,7 +700,6 @@ static int _auto_gc_bb_find(scf_basic_block_t* bb, scf_function_t* f)
 
                _bb_del_ds(cur_bb, ds_obj);
                count++;
-
 ref:
                while (dn) {
                        if (SCF_OP_TYPE_CAST == dn->type)
@@ -536,102 +711,34 @@ ref:
                                break;
                }
 
-               if (SCF_OP_CALL == dn->type || dn->node->split_flag) {
-
-                       if (dn->node->split_flag) {
-                               assert(SCF_OP_CALL   == dn->node->split_parent->type
-                                       || SCF_OP_CREATE == dn->node->split_parent->type);
-                       }
-
-                       scf_dag_node_t* dn_pf = dn->childs->data[0];
-                       scf_function_t* f2    = dn_pf->var->func_ptr;
-                       scf_variable_t* ret   = f2->rets->data[0];
-
-                       scf_logd("f2: %s, ret->auto_gc_flag: %d\n", f2->node.w->text->data, ret->auto_gc_flag);
-
-                       if (!strcmp(f2->node.w->text->data, "scf__auto_malloc")) {
-                               _bb_add_ds(cur_bb, ds_obj);
-                               count++;
-
-                               scf_dn_status_free(ds_obj);
-                               ds_obj = NULL;
-                               goto end;
-
-                       } else if (ret->auto_gc_flag) {
-
-                               if (cur_bb != bb) {
-                                       scf_list_del(&c->list);
-                                       scf_list_add_tail(&cur_bb->code_list_head, &c->list);
-                               }
-
-                               _bb_add_ds        (cur_bb, ds_obj);
-                               _bb_add_ds_for_ret(cur_bb, ds_obj, f2);
-
-                               ds = scf_dn_status_alloc(dn);
-                               if (!ds) {
-                                       scf_dn_status_free(ds_obj);
-                                       return -ENOMEM;
-                               }
-                               _bb_del_ds(cur_bb, ds);
-
-                               scf_dn_status_free(ds);
-                               ds = NULL;
-
-                               if (l != scf_list_sentinel(&bb->code_list_head)) {
+               ret = _auto_gc_find_ref(ds_obj, dn, c, bb, cur_bb, f);
+               if (ret < 0) {
+                       scf_dn_status_free(ds_obj);
+                       return ret;
+               }
 
-                                       AUTO_GC_FIND_BB_SPLIT(cur_bb, bb2);
-                                       cur_bb = bb2;
-                                       scf_vector_add_unique(cur_bb->dn_reloads, ds_obj->dag_node);
-                               }
+               count += ret > 0;
 
-                               scf_dn_status_free(ds_obj);
-                               ds_obj = NULL;
+               if (cur_bb != bb) {
+                       scf_list_del(&c->list);
+                       scf_list_add_tail(&cur_bb->code_list_head, &c->list);
+               }
 
-                               count++;
-                               continue;
-                       }
-               } else {
-                       ds  = NULL;
-                       ret = scf_ds_for_dn(&ds, dn);
-                       if (ret < 0) {
-                               scf_dn_status_free(ds_obj);
-                               return ret;
-                       }
+               if (ret > 1 && l != scf_list_sentinel(&bb->code_list_head)) {
 
-                       ret = _bb_find_ds_alias(ds, c, bb, &f->basic_block_list_head);
+                       AUTO_GC_FIND_BB_SPLIT(cur_bb, bb2);
+                       cur_bb = bb2;
 
-                       scf_dn_status_free(ds);
-                       ds = NULL;
+                       ret = scf_vector_add_unique(cur_bb->entry_dn_actives, ds_obj->dag_node);
                        if (ret < 0) {
                                scf_dn_status_free(ds_obj);
                                return ret;
                        }
-
-                       if (1 == ret) {
-                               if (cur_bb != bb) {
-                                       scf_list_del(&c->list);
-                                       scf_list_add_tail(&cur_bb->code_list_head, &c->list);
-                               }
-
-                               _bb_add_ds(cur_bb, ds_obj);
-
-                               if (l != scf_list_sentinel(&bb->code_list_head)) {
-
-                                       AUTO_GC_FIND_BB_SPLIT(cur_bb, bb2);
-                                       cur_bb = bb2;
-                                       scf_vector_add_unique(cur_bb->dn_reloads, ds_obj->dag_node);
-                               }
-
-                               scf_dn_status_free(ds_obj);
-                               ds_obj = NULL;
-
-                               count++;
-                               continue;
-                       }
                }
 
                scf_dn_status_free(ds_obj);
                ds_obj = NULL;
+               continue;
 end:
                if (cur_bb != bb) {
                        scf_list_del(&c->list);
@@ -691,12 +798,13 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t*
        scf_basic_block_t* bb;
        scf_dn_status_t*   ds;
        scf_3ac_code_t*    c;
+       scf_variable_t*    fret;
 
        int total = 0;
-       int count;
+       int count = 0;
        int ret;
 
-       scf_logw("f: %s\n", f->node.w->text->data);
+       scf_logw("--- %s() ---\n", f->node.w->text->data);
 
        do {
                for (l = scf_list_head(bb_list_head); l != scf_list_sentinel(bb_list_head); ) {
@@ -733,24 +841,27 @@ static int _auto_gc_function_find(scf_ast_t* ast, scf_function_t* f, scf_list_t*
        int i;
        for (i = 0; i < bb->ds_malloced->size; i++) {
                ds =        bb->ds_malloced->data[i];
+
+               if (!ds->ret_flag)
+                       continue;
 #if 1
-               scf_logi("ds->ret: %u, ds->dag_node->var->arg_flag: %u\n", ds->ret, ds->dag_node->var->arg_flag);
+               scf_logi("ds: %#lx, ds->ret_flag: %u, ds->ret_index: %d, ds->dag_node->var->arg_flag: %u\n",
+                               0xffff & (uintptr_t)ds, ds->ret_flag, ds->ret_index, ds->dag_node->var->arg_flag);
                scf_dn_status_print(ds);
-               printf("\n");
 #endif
-               if (!ds->ret)
-                       continue;
 
                if (ds->dag_node->var->arg_flag)
                        ds->dag_node->var->auto_gc_flag = 1;
                else {
-                       scf_variable_t* ret = f->rets->data[0];
-                       ret->auto_gc_flag = 1;
+                       assert(ds->ret_index < f->rets->size);
+
+                       fret = f->rets->data[ds->ret_index];
+                       fret->auto_gc_flag = 1;
 
                        _bb_find_ds_alias_leak(ds, c, bb, bb_list_head);
                }
        }
-       scf_logi("f: %s *****\n\n", f->node.w->text->data);
+       scf_logi("--- %s() ---\n\n", f->node.w->text->data);
 
        return total;
 }
index c2d5ec292dbcd45eeff8338a37f75172839987e8..cb026e85e2baeeb484a69f664743ab0c1ffffac8 100644 (file)
@@ -68,31 +68,29 @@ static int _optimize_generate_loads_saves(scf_ast_t* ast, scf_function_t* f, scf
 
                bb->index = f->nb_basic_blocks++;
 
-               if (bb->generate_flag) {
-                       for (i = 0; i < bb->dn_loads->size; i++) {
-                               dn =        bb->dn_loads->data[i];
+               for (i = 0; i < bb->dn_loads->size; i++) {
+                       dn =        bb->dn_loads->data[i];
 
-                               if (scf_vector_find(bb->dn_reloads, dn))
-                                       continue;
+                       if (scf_vector_find(bb->dn_reloads, dn))
+                               continue;
 
-                               SCF_OPTIMIZER_LOAD(SCF_OP_3AC_LOAD, &bb->code_list_head);
-                       }
+                       SCF_OPTIMIZER_LOAD(SCF_OP_3AC_LOAD, &bb->code_list_head);
+               }
 
-                       for (i = 0; i < bb->dn_saves->size; i++) {
-                               dn =        bb->dn_saves->data[i];
+               for (i = 0; i < bb->dn_saves->size; i++) {
+                       dn =        bb->dn_saves->data[i];
 
-                               if (scf_vector_find(bb->dn_resaves, dn))
-                                       continue;
+                       if (scf_vector_find(bb->dn_resaves, dn))
+                               continue;
 
-                               if (bb->loop_flag)
-                                       SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->save_list_head);
-                               else {
-                                       SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->code_list_head);
+                       if (bb->loop_flag)
+                               SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->save_list_head);
+                       else {
+                               SCF_OPTIMIZER_SAVE(SCF_OP_3AC_SAVE, &bb->code_list_head);
 
-                                       if (bb->cmp_flag) {
-                                               scf_list_del(&save->list);
-                                               scf_list_add_front(&bb->code_list_head, &save->list);
-                                       }
+                               if (bb->cmp_flag) {
+                                       scf_list_del(&save->list);
+                                       scf_list_add_front(&bb->code_list_head, &save->list);
                                }
                        }
                }
@@ -113,16 +111,18 @@ static int _optimize_generate_loads_saves(scf_ast_t* ast, scf_function_t* f, scf
                }
 
                if (bb->auto_ref_flag || bb->auto_free_flag) {
-
+#if 1
                        scf_3ac_code_t* c0 = scf_3ac_code_alloc();
                        scf_3ac_code_t* c1 = scf_3ac_code_alloc();
 
-                       c0->op = scf_3ac_find_operator(SCF_OP_3AC_PUSH_RAX);
-                       c1->op = scf_3ac_find_operator(SCF_OP_3AC_POP_RAX);
+                       c0->op = scf_3ac_find_operator(SCF_OP_3AC_PUSH_RETS);
+                       c1->op = scf_3ac_find_operator(SCF_OP_3AC_POP_RETS);
 
                        scf_list_add_front(&bb->code_list_head, &c0->list);
                        scf_list_add_tail(&bb->code_list_head,  &c1->list);
+#endif
                }
+
 #if 1
                scf_logd("bb: %p, bb->index: %d\n", bb, bb->index);
                ret = scf_basic_block_active_vars(bb);
diff --git a/examples/auto_gc_multi_rets.c b/examples/auto_gc_multi_rets.c
new file mode 100644 (file)
index 0000000..ee8be80
--- /dev/null
@@ -0,0 +1,27 @@
+
+#include "../lib/scf_capi.c"
+
+int*, int* f()
+{
+       int* p0 = scf__auto_malloc(sizeof(int));
+       int* p1 = scf__auto_malloc(sizeof(int));
+
+       *p0 = 1;
+       *p1 = 2;
+
+       return p0, p1;
+}
+
+int main(int argc, char* argv[])
+{
+       int* p0;
+       int* p1;
+
+       p0, p1 = f();
+
+       if (argc > 1)
+               return 1;
+
+       printf("%d, %d\n", *p0, *p1);
+       return 0;
+}
index fb99a1c2f09d9e4823e63cd726d74f2e5942dcae..aa4f5ef6a0695769dd7ef69babe3ec43bbb35e44 100644 (file)
@@ -66,76 +66,8 @@ struct mat
                return 0;
        }
 
-/*     int operator+=(mat* this, mat* that)
-       {
-               if (this->depth != that->depth
-                               || this->width  != that->width
-                               || this->height != that->height
-                               || this->count  != that->count
-                               || this->type   != that->type)
-                       return -1;
-
-               if (MAT_TYPE_DOUBLE != this->type)
-                       return -1;
-
-               int64_t c;
-               int64_t y;
-               int64_t x;
-               int64_t z;
-
-               double* d0 = (double*)this->data;
-               double* d1 = (double*)that->data;
-
-               for (c = 0; c < this->count; c++) {
-
-                       int64_t c0 = this->c + this->cstep * c;
-                       int64_t c1 = that->c + that->cstep * c;
-
-                       int64_t coffset0 = c0 * this->height * this->xstride;
-                       int64_t coffset1 = c1 * that->height * that->xstride;
-
-                       for (y = 0; y < this->height; y++) {
-
-                               int64_t y0 = this->y + this->ystep * y;
-                               int64_t y1 = that->y + that->ystep * y;
-
-                               int64_t yoffset0 = y0 * this->xstride * this->depth;
-                               int64_t yoffset1 = y1 * that->xstride * that->depth;
-
-                               for (x = 0; x < this->width; x++) {
-
-                                       int64_t x0 = this->x + this->xstep * x;
-                                       int64_t x1 = that->x + that->xstep * x;
-
-                                       int64_t xoffset0 = x0 * this->depth;
-                                       int64_t xoffset1 = x1 * that->depth;
-
-                                       for (z = 0; z < this->depth; z++) {
-
-                                               int64_t z0 = this->z + this->zstep * z;
-                                               int64_t z1 = that->z + that->zstep * z;
-
-                                               d0[coffset0 + yoffset0 + xoffset0 + z0] += d1[coffset1 + yoffset1 + xoffset1 + z1];
-                                       }
-                               }
-                       }
-               }
-
-               return 0;
-       }
-*/
        mat*, int operator+(mat* this, mat* that)
        {
-/*             if (this->depth != that->depth
-                               || this->width  != that->width
-                               || this->height != that->height
-                               || this->count  != that->count
-                               || this->type   != that->type)
-                       return NULL, -1;
-
-               if (MAT_TYPE_DOUBLE != this->type)
-                       return NULL, -1;
-*/
                mat* res;
 
                res = create mat(MAT_TYPE_DOUBLE, NULL, this->depth, this->width, this->height, this->count);
@@ -217,15 +149,12 @@ int main()
        m2 = create mat(MAT_TYPE_DOUBLE, (uint8_t*)c, 1, 2, 2, 1);
 
        m3 = m0 + m1 + m2;
-//     scf_printf("%s(),%d\n", __func__, __LINE__);
 
        double* dd = (double*)m3->data;
 
        int i;
        for (i = 0; i < 4; i++)
                printf("m3: %lf\n", dd[i]);
-//             scf_printf("m1: %lf\n", *(double*)(m1->data + i * sizeof(double)));
 
        return 0;
 }
-
index fd0c4fd6cd3fcdebf6fd738480358e6ec7545f48..6231fb166443978059a98de44c88484a9392f165 100644 (file)
@@ -5729,8 +5729,8 @@ static risc_inst_handler_pt  risc_inst_handlers[SCF_N_3AC_OPS] =
        [SCF_OP_3AC_INC     ]  =  _risc_inst_inc_handler,
        [SCF_OP_3AC_DEC     ]  =  _risc_inst_dec_handler,
 
-       [SCF_OP_3AC_PUSH_RAX]  =  _risc_inst_push_rax_handler,
-       [SCF_OP_3AC_POP_RAX ]  =  _risc_inst_pop_rax_handler,
+       [SCF_OP_3AC_PUSH_RETS] =  _risc_inst_push_rax_handler,
+       [SCF_OP_3AC_POP_RETS ] =  _risc_inst_pop_rax_handler,
 
        [SCF_OP_3AC_MEMSET  ]  =  _risc_inst_memset_handler,
 
index 82eb8e4f744a21db5b484a4688bda86a22ab9c05..629ce91da086efd24ed5c77cb07d9e139b2a463d 100644 (file)
@@ -1220,8 +1220,8 @@ static risc_rcg_handler_pt  risc_rcg_handlers[SCF_N_3AC_OPS] =
        [SCF_OP_3AC_INC     ]  =  _risc_rcg_inc_handler,
        [SCF_OP_3AC_DEC     ]  =  _risc_rcg_dec_handler,
 
-       [SCF_OP_3AC_PUSH_RAX]  =  _risc_rcg_push_rax_handler,
-       [SCF_OP_3AC_POP_RAX ]  =  _risc_rcg_pop_rax_handler,
+       [SCF_OP_3AC_PUSH_RETS] =  _risc_rcg_push_rax_handler,
+       [SCF_OP_3AC_POP_RETS ] =  _risc_rcg_pop_rax_handler,
 
        [SCF_OP_3AC_MEMSET  ]  =  _risc_rcg_memset_handler,
 
index be0cd86be4a0bbcca2f0edacf913237a3b176ffb..951ef23312c53f5d8046160b928850e98d218860 100644 (file)
@@ -1844,7 +1844,7 @@ static int _x64_inst_address_of_pointer_handler(scf_native_t* ctx, scf_3ac_code_
        return x64_inst_pointer(ctx, c, 1);
 }
 
-static int _x64_inst_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+static int _x64_inst_push_rets_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 {
        if (!c->instructions) {
                c->instructions = scf_vector_alloc();
@@ -1852,19 +1852,34 @@ static int _x64_inst_push_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                        return -ENOMEM;
        }
 
-       scf_register_t*     rax  = x64_find_register("rax");
-       scf_x64_OpCode_t*   push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G);
+       scf_x64_context_t*  x64 = ctx->priv;
+       scf_function_t*     f   = x64->f;
+
        scf_instruction_t*  inst;
+       scf_x64_OpCode_t*   push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G);
+       scf_register_t*     r;
 
-       inst = x64_make_inst_G(push, rax);
-       X64_INST_ADD_CHECK(c->instructions, inst);
+       int n = 0;
+       int i;
+
+       if (!f->void_flag) {
+               n = f->rets->size;
+
+               if (n > X64_ABI_RET_NB)
+                       return -EINVAL;
+       }
+
+       for (i = 0; i < n; i++) {
+               r  = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[i], 8);
+
+               inst = x64_make_inst_G(push, r);
+               X64_INST_ADD_CHECK(c->instructions, inst);
+       }
 
-       inst = x64_make_inst_G(push, rax);
-       X64_INST_ADD_CHECK(c->instructions, inst);
        return 0;
 }
 
-static int _x64_inst_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c)
+static int _x64_inst_pop_rets_handler(scf_native_t* ctx, scf_3ac_code_t* c)
 {
        if (!c->instructions) {
                c->instructions = scf_vector_alloc();
@@ -1872,15 +1887,30 @@ static int _x64_inst_pop_rax_handler(scf_native_t* ctx, scf_3ac_code_t* c)
                        return -ENOMEM;
        }
 
-       scf_register_t*     rax  = x64_find_register("rax");
-       scf_x64_OpCode_t*   pop  = x64_find_OpCode(SCF_X64_POP, 8,8, SCF_X64_G);
+       scf_x64_context_t*  x64 = ctx->priv;
+       scf_function_t*     f   = x64->f;
+
        scf_instruction_t*  inst;
+       scf_x64_OpCode_t*   pop  = x64_find_OpCode(SCF_X64_POP, 8,8, SCF_X64_G);
+       scf_register_t*     r;
 
-       inst = x64_make_inst_G(pop, rax);
-       X64_INST_ADD_CHECK(c->instructions, inst);
+       int n = 0;
+       int i;
+
+       if (!f->void_flag) {
+               n = f->rets->size;
+
+               if (n > X64_ABI_RET_NB)
+                       return -EINVAL;
+       }
+
+       for (i = n - 1; i >= 0; i--) {
+               r  = x64_find_register_type_id_bytes(0, x64_abi_ret_regs[i], 8);
+
+               inst = x64_make_inst_G(pop, r);
+               X64_INST_ADD_CHECK(c->instructions, inst);
+       }
 
-       inst = x64_make_inst_G(pop, rax);
-       X64_INST_ADD_CHECK(c->instructions, inst);
        return 0;
 }
 
@@ -2228,8 +2258,8 @@ static x64_inst_handler_pt  x64_inst_handlers[] =
        [SCF_OP_3AC_INC     ]  =  _x64_inst_inc_handler,
        [SCF_OP_3AC_DEC     ]  =  _x64_inst_dec_handler,
 
-       [SCF_OP_3AC_PUSH_RAX]  =  _x64_inst_push_rax_handler,
-       [SCF_OP_3AC_POP_RAX ]  =  _x64_inst_pop_rax_handler,
+       [SCF_OP_3AC_PUSH_RETS] =  _x64_inst_push_rets_handler,
+       [SCF_OP_3AC_POP_RETS]  =  _x64_inst_pop_rets_handler,
 
        [SCF_OP_3AC_MEMSET  ]  =  _x64_inst_memset_handler,
 
index 63a6b512fcb5fc4a2d108a1c7b6a3e16af960f1f..332b805f304fedbe3ea17ede28ce630f006af190 100644 (file)
@@ -1322,8 +1322,8 @@ static x64_rcg_handler_pt  x64_rcg_handlers[SCF_N_3AC_OPS] =
        [SCF_OP_3AC_INC     ]  =  _x64_rcg_inc_handler,
        [SCF_OP_3AC_DEC     ]  =  _x64_rcg_dec_handler,
 
-       [SCF_OP_3AC_PUSH_RAX]  =  _x64_rcg_push_rax_handler,
-       [SCF_OP_3AC_POP_RAX ]  =  _x64_rcg_pop_rax_handler,
+       [SCF_OP_3AC_PUSH_RETS] =  _x64_rcg_push_rax_handler,
+       [SCF_OP_3AC_POP_RETS]  =  _x64_rcg_pop_rax_handler,
 
        [SCF_OP_3AC_MEMSET  ]  =  _x64_rcg_memset_handler,
 
index 9bbe184b0aa7c313d0c4aa850aacdc81b9cf986b..2e7fe3299978ac16d9804d28ec0ca09e5258c2e3 100644 (file)
@@ -94,6 +94,8 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d)
                return SCF_DFA_ERROR;
        }
 
+       f->void_flag = void_flag;
+
        if (f->rets->size > 4) {
                scf_loge("function return values must NOT more than 4!\n");
                return SCF_DFA_ERROR;
index 3e546780732b41294403b8f934a8d6d598094e0d..2d1abae85ccff7dddc591c4dd3cb554ea1c6ef4b 100644 (file)
@@ -254,7 +254,8 @@ static int _operator_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data)
                }
        } else {
                scf_operator_t* op = scf_find_base_operator(d->current_function->node.w->text->data, d->current_function->argv->size);
-               if (!op) {
+
+               if (!op || !op->signature) {
                        scf_loge("operator: '%s', nb_operands: %d\n",
                                        d->current_function->node.w->text->data, d->current_function->argv->size);
                        return SCF_DFA_ERROR;
index 7a1294a0e95c267cbc9bc7a4c18fc0e22061fa20..7294b5f81d32fd6e2ce315e95bee53f2991d53df 100644 (file)
@@ -2593,8 +2593,8 @@ static int _semantic_multi_rets_assign(scf_ast_t* ast, scf_node_t** nodes, int n
 
        assert(call->nb_nodes > 0);
 
-       scf_loge("rets->nb_nodes: %d, call->result_nodes: %p\n", rets->nb_nodes, call->result_nodes);
-       scf_loge("rets->nb_nodes: %d, call->result_nodes->size: %d\n", rets->nb_nodes, call->result_nodes->size);
+       scf_logd("rets->nb_nodes: %d, call->result_nodes: %p\n", rets->nb_nodes, call->result_nodes);
+       scf_logd("rets->nb_nodes: %d, call->result_nodes->size: %d\n", rets->nb_nodes, call->result_nodes->size);
 
        assert(rets->nb_nodes <= call->result_nodes->size);