00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00043 #include "ctrump/analyzer/cfg.h"
00044 #include "ctrump/common/bitmap.h"
00045 #include "ctrump/common/varray.h"
00046 #include "ctrump/common/uthash.h"
00047 #include "ctrump/common/intmap.h"
00048 #include "ctrump/common/abort.h"
00049 #include "ctrump/ast/ast.h"
00050 #include "ctrump/analyzer/peel.h"
00051
00052 #include <stdlib.h>
00053 #include <stdio.h>
00054 #include <stdint.h>
00055 #include <assert.h>
00056
00057 enum partial_bb_expr_code {
00058 BB_EXPR
00059 };
00060
00064 struct partial_bb_expr {
00065 enum partial_bb_expr_code code;
00066 struct ctrump_stmt *at;
00067
00068 union {
00069 struct ctrump_expr *expr;
00070 }u;
00071 };
00072
00076 struct pending_chain {
00077 struct pending_chain *chain;
00078 struct ctrump_bb **resolve_ptr;
00079 };
00080
00081 enum load_store_t {
00082 INIT,
00083 LOAD,
00084 STORE
00085 };
00086
00090 struct ordered_load_store_node {
00091 enum load_store_t code;
00092 int op_idx;
00093 int var_idx;
00094 };
00095
00099 struct partial_bb {
00100 int id;
00101 int flags;
00102 struct ctrump_varray preds, succs, exprs, dfs, children;
00103 struct ctrump_varray refs, stores;
00104 struct ctrump_varray inits;
00105 struct ctrump_varray arr_loads, arr_stores;
00106 struct ctrump_varray ordered_load_store;
00107 struct ctrump_varray ordered_mem_load_store;
00108 struct partial_bb *idom;
00109 struct pending_chain *resolve_pending;
00110 struct ctrump_loop_cfg_info *loop_cfg;
00111 int order;
00112 ctrump_bitmap_t use, kill, live, phi_inserted;
00113 struct ctrump_bb *bb;
00114
00115 int num_phi;
00116 struct ctrump_phi_node *phi_nodes;
00117 };
00118
00122 struct partial_var_info {
00123 struct ctrump_cfg_var_info result;
00124 ctrump_bitmap_t modified_at;
00125 struct ctrump_varray ssa_var_stack;
00126 struct ctrump_varray stack_depth;
00127 int map_val;
00128 };
00129
00133 struct label_table {
00134 const struct ctrump_symbol *label_symbol;
00135 struct ctrump_stmt *stmt;
00136 UT_hash_handle hh;
00137 };
00138
00142 struct build_cfg_env {
00143 struct ctrump_mempool *cfg_pool;
00144 struct ctrump_build_cfg_error *error;
00145 struct ctrump_mempool tmp_alloc;
00146 struct label_table *label_table;
00147
00148 struct partial_bb **stmt_bb_table;
00149 struct partial_bb **dfs_order;
00150 ctrump_bitmap_t label_ref_bmp;
00151 int bb_id;
00152 int next_id;
00153 struct ctrump_varray basic_blocks;
00154 };
00155
00156 static struct partial_bb *new_bb(struct build_cfg_env *env,
00157 struct ctrump_loop_cfg_info *cfg);
00158 static void append_succs_maybe(struct partial_bb *bb,
00159 struct partial_bb *next,
00160 struct build_cfg_env *env);
00161 static void append_succs(struct partial_bb *bb,
00162 struct partial_bb *next,
00163 struct build_cfg_env *env);
00164
00165 static void build_cfg_expr_maybe(struct ctrump_expr *e,
00166 struct ctrump_stmt *at,
00167 struct build_cfg_env *env,
00168 struct ctrump_loop_cfg_info *cur_loop,
00169 struct partial_bb **current_bb_ptr);
00170
00171 static void build_cfg_expr(struct ctrump_expr *e,
00172 struct ctrump_stmt *at,
00173 struct build_cfg_env *env,
00174 struct ctrump_loop_cfg_info *cur_loop,
00175 struct partial_bb **current_bb_ptr);
00176
00177 static void build_cfg_initializer(struct ctrump_initializer *init,
00178 struct ctrump_stmt *stmt,
00179 struct build_cfg_env *env,
00180 struct ctrump_loop_cfg_info *loop,
00181 struct partial_bb **current_bb_ptr);
00182
00183 static void build_cfg_initializer_list(struct ctrump_initializer_list *list,
00184 struct ctrump_stmt *stmt,
00185 struct build_cfg_env *env,
00186 struct ctrump_loop_cfg_info *loop,
00187 struct partial_bb **current_bb_ptr);
00188
00189 #define zero_bmp ctrump_bmp_zero
00190
00191 #define HASH_FIND_SYM(head,findptr,out) \
00192 HASH_FIND(hh,head,findptr,sizeof(struct ctrump_symbol*),out)
00193
00197 static void
00198 delete_table(struct label_table *table)
00199 {
00200 struct label_table *t;
00201 while (table) {
00202 t = table;
00203 HASH_DEL(table, t);
00204 free(t);
00205 }
00206 }
00207
00211 static int
00212 build_label_table(struct label_table **table,
00213 const struct ctrump_compound_stmt *stmts,
00214 struct build_cfg_env *env)
00215 {
00216 struct ctrump_stmt *itm = stmts->items;
00217 int i, nitem = stmts->num_item;
00218 for (i=0; i<nitem; i++) {
00219 struct ctrump_stmt *stmt = &itm[i];
00220 if (stmt->code == CTRUMP_STMT_LABELED) {
00221 struct label_table *find, *t;
00222 const struct ctrump_symbol *label_symbol;
00223 label_symbol = stmt->u.labeled.label_symbol;
00224
00225 HASH_FIND_SYM((*table), stmt->u.labeled.label_symbol, find);
00226
00227 if (find) {
00228 env->error->code = CTRUMP_BUILD_CFG_ERROR_REDEFINE_LABEL;
00229 env->error->stmt = stmt;
00230
00231 delete_table(*table);
00232
00233 return -1;
00234 }
00235
00236 t = ctrump_mempool_alloc(&env->tmp_alloc, sizeof(*t));
00237
00238 t->label_symbol = label_symbol;
00239 t->stmt = stmt;
00240 HASH_ADD(hh, *table, label_symbol, sizeof(struct ctrump_symbol), t);
00241 } else if (stmt->code == CTRUMP_STMT_COMPOUND) {
00242 const struct ctrump_compound_stmt *comp = &stmt->u.compound;
00243 return build_label_table(table, comp, env);
00244 }
00245 }
00246
00247 return 0;
00248 }
00249
00253 static int
00254 build_label_ref(struct label_table *table,
00255 const struct ctrump_compound_stmt *stmt,
00256 struct build_cfg_env *env)
00257 {
00258 struct ctrump_stmt *itm = stmt->items;
00259 int i, nitem = stmt->num_item;
00260 for (i=0; i<nitem; i++) {
00261 struct ctrump_stmt *stmt = &itm[i];
00262 if (stmt->code == CTRUMP_STMT_GOTO) {
00263 const struct ctrump_goto_stmt *s = &stmt->u.goto_;
00264 struct label_table *t;
00265 HASH_FIND_SYM(table, s->label, t);
00266
00267 if (t == NULL) {
00268 env->error->code = CTRUMP_BUILD_CFG_ERROR_UNDEFINED_LABEL;
00269 env->error->stmt = stmt;
00270
00271 return -1;
00272 }
00273
00274 ctrump_bitmap_set(env->label_ref_bmp, stmt->id);
00275 return 0;
00276 } else if (stmt->code == CTRUMP_STMT_COMPOUND) {
00277 const struct ctrump_compound_stmt *comp = &stmt->u.compound;
00278 return build_label_ref(table, comp, env);
00279 }
00280 }
00281
00282 return 0;
00283 }
00284
00288 static int
00289 check_label_use(struct build_cfg_env *env,
00290 const struct ctrump_compound_stmt *stmts)
00291 {
00292 struct label_table *table = NULL;
00293 int r;
00294
00295 r = build_label_table(&table, stmts, env);
00296 if (r < 0)
00297 goto fail;
00298
00299 r = build_label_ref(table, stmts, env);
00300 if (r < 0)
00301 goto fail;
00302
00303 env->label_table = table;
00304 return 0;
00305
00306 fail:
00307 delete_table(table);
00308 return r;
00309 }
00310
00331 static void
00332 build_cfg_logical_expr(struct ctrump_expr *lhs,
00333 struct ctrump_expr *rhs,
00334 struct ctrump_stmt *at,
00335 struct build_cfg_env *env,
00336 struct ctrump_loop_cfg_info *cur_loop,
00337 struct partial_bb **current_bb_ptr)
00338 {
00339 struct partial_bb *next_bb = new_bb(env, cur_loop);
00340 struct partial_bb *rhs_bb = new_bb(env, cur_loop);
00341
00342 build_cfg_expr(lhs, at, env, cur_loop, current_bb_ptr);
00343 append_succs(*current_bb_ptr, next_bb, env);
00344 append_succs(*current_bb_ptr, rhs_bb, env);
00345
00346 build_cfg_expr(rhs, at, env, cur_loop, &rhs_bb);
00347 append_succs(rhs_bb, next_bb, env);
00348
00349 *current_bb_ptr = next_bb;
00350 }
00351
00355 static void
00356 build_cfg_trinary_cond_expr(struct ctrump_expr *cond,
00357 struct ctrump_expr *then_,
00358 struct ctrump_expr *else_,
00359 struct ctrump_stmt *at,
00360 struct build_cfg_env *env,
00361 struct ctrump_loop_cfg_info *cur_loop,
00362 struct partial_bb **current_bb_ptr)
00363 {
00364 struct partial_bb *next_bb = new_bb(env, cur_loop);
00365 struct partial_bb *then_bb = new_bb(env, cur_loop);
00366 struct partial_bb *else_bb = new_bb(env, cur_loop);
00367
00368 build_cfg_expr(cond, at, env,cur_loop, current_bb_ptr);
00369 append_succs(*current_bb_ptr, then_bb, env);
00370 append_succs(*current_bb_ptr, else_bb, env);
00371 build_cfg_expr(then_, at, env, cur_loop, &then_bb);
00372 build_cfg_expr(else_, at, env, cur_loop, &else_bb);
00373
00374 append_succs(then_bb, next_bb, env);
00375 append_succs(else_bb, next_bb, env);
00376
00377 *current_bb_ptr = next_bb;
00378 }
00379
00383 struct flow_env {
00384 struct partial_bb *continue_to;
00385 struct partial_bb *break_to;
00386 struct partial_bb *return_to;
00387 struct ctrump_loop_cfg_info *loop_cfg;
00388 };
00389
00394 static void
00395 build_cfg_cond_expr(struct ctrump_expr *e,
00396 struct ctrump_stmt *at,
00397 struct build_cfg_env *env,
00398 struct ctrump_loop_cfg_info *cur_loop,
00399 struct partial_bb **current_bb_ptr)
00400 {
00401 int i, n;
00402 struct ctrump_expr *args;
00403
00404 tailcall:
00405 switch (e->code) {
00406 case CTRUMP_EXPR_BIN_ASSIGN:
00407 case CTRUMP_EXPR_BIN_COMMA:
00408 case CTRUMP_CASE_BIN_ARITH_EXPR:
00409 case CTRUMP_CASE_BIN_EQ_EXPR:
00410 case CTRUMP_CASE_BIN_OP_ASSIGN_EXPR:
00411 build_cfg_cond_expr(e->u.binary.lhs, at, env, cur_loop, current_bb_ptr);
00412 e = e->u.binary.rhs;
00413 goto tailcall;
00414
00415 case CTRUMP_EXPR_ARRREF:
00416 build_cfg_cond_expr(e->u.arr_ref.array, at, env, cur_loop, current_bb_ptr);
00417 e = e->u.arr_ref.subscript;
00418 goto tailcall;
00419
00420 case CTRUMP_EXPR_MEMBER_REF:
00421 case CTRUMP_EXPR_PTR_MEMBER_REF:
00422 e = e->u.member_ref.obj_expr;
00423 goto tailcall;
00424
00425 case CTRUMP_CASE_ALL_UNARY_EXPR:
00426 e = e->u.unary.expr;
00427 goto tailcall;
00428
00429 case CTRUMP_EXPR_PAREN:
00430 e = e->u.paren.expr;
00431 goto tailcall;
00432
00433 case CTRUMP_EXPR_CALL:
00434 n = e->u.call.num_args;
00435 args = e->u.call.args;
00436 for (i=0; i<n; i++) {
00437 build_cfg_cond_expr(&args[i], at, env, cur_loop, current_bb_ptr);
00438 }
00439 e = e->u.call.func_expr;
00440 goto tailcall;
00441
00442 case CTRUMP_EXPR_VARREF:
00443 case CTRUMP_CASE_CONSTANT_TERM:
00444 case CTRUMP_EXPR_EMPTY:
00445 return;
00446
00447 case CTRUMP_EXPR_CAST:
00448 e = e->u.cast.expr;
00449 goto tailcall;
00450
00451 case CTRUMP_EXPR_IMPLICIT_CAST:
00452 e = e->u.implicit_cast.expr;
00453 goto tailcall;
00454
00455 case CTRUMP_EXPR_MACRO_EXPAND:
00456 e = e->u.macro_expand.expanded;
00457 goto tailcall;
00458
00459 case CTRUMP_CASE_BIN_LOG_EXPR:
00460 build_cfg_logical_expr(e->u.binary.lhs, e->u.binary.rhs, at, env, cur_loop, current_bb_ptr);
00461 break;
00462
00463 case CTRUMP_EXPR_CONDITIONAL:
00464 build_cfg_trinary_cond_expr(e->u.cond.cond, e->u.cond.then_, e->u.cond.else_, at, env, cur_loop, current_bb_ptr);
00465 break;
00466
00467 case CTRUMP_EXPR_INITIALIZER:
00468 build_cfg_initializer_list(&e->u.initializer.initializer, at, env, cur_loop, current_bb_ptr);
00469 break;
00470
00471 case CTRUMP_EXPR_TEXT:
00472 case CTRUMP_EXPR_IVTMP:
00473
00474 ctrump_unreachable("invalid expr code");
00475 }
00476 }
00477
00481 static void
00482 build_cfg_expr(struct ctrump_expr *e,
00483 struct ctrump_stmt *at,
00484 struct build_cfg_env *env,
00485 struct ctrump_loop_cfg_info *cur_loop,
00486 struct partial_bb **current_bb_ptr)
00487 {
00488 struct partial_bb_expr *p;
00489 struct partial_bb *bb = *current_bb_ptr;
00490 VA_NEWELEM_P(&bb->exprs, &env->tmp_alloc);
00491 p = VA_LAST_PTR(struct partial_bb_expr, &bb->exprs);
00492
00493 build_cfg_cond_expr(e, at, env, cur_loop, current_bb_ptr);
00494
00495 p->code = BB_EXPR;
00496 p->u.expr = e;
00497 p->at = at;
00498 }
00499
00514 static void
00515 append_pending(struct build_cfg_env *env,
00516 struct partial_bb *bb,
00517 struct ctrump_bb **resolve_ptr)
00518 {
00519 struct pending_chain *pend = ctrump_mempool_alloc(&env->tmp_alloc,
00520 sizeof(*pend));
00521 pend->chain = bb->resolve_pending;
00522 bb->resolve_pending = pend;
00523 pend->resolve_ptr = resolve_ptr;
00524 }
00525
00526
00531 static void
00532 build_cfg_expr_maybe(struct ctrump_expr *e,
00533 struct ctrump_stmt *at,
00534 struct build_cfg_env *env,
00535 struct ctrump_loop_cfg_info *cur_loop,
00536 struct partial_bb **current_bb_ptr)
00537 {
00538 if (*current_bb_ptr) {
00539 build_cfg_expr(e, at, env, cur_loop, current_bb_ptr);
00540 }
00541 }
00542
00543
00548 static void
00549 append_succs(struct partial_bb *bb,
00550 struct partial_bb *next,
00551 struct build_cfg_env *env)
00552 {
00553 VA_PUSH_P(struct partial_bb*, &bb->succs, next, &env->tmp_alloc);
00554 VA_PUSH_P(struct partial_bb*, &next->preds, bb, &env->tmp_alloc);
00555 }
00556
00557
00562 static void
00563 append_succs_maybe(struct partial_bb *bb,
00564 struct partial_bb *next,
00565 struct build_cfg_env *env)
00566 {
00567 if (bb) {
00568 append_succs(bb, next, env);
00569 }
00570 }
00571
00572
00576 static struct partial_bb *
00577 new_bb(struct build_cfg_env *env, struct ctrump_loop_cfg_info *loop)
00578 {
00579 struct partial_bb *ret = ctrump_mempool_alloc(&env->tmp_alloc, sizeof(*ret));
00580 ret->id = env->bb_id++;
00581 ret->resolve_pending = NULL;
00582 ctrump_varray_init_pool(&ret->preds, 4, sizeof(struct partial_bb*), &env->tmp_alloc);
00583 ctrump_varray_init_pool(&ret->succs, 4, sizeof(struct partial_bb*), &env->tmp_alloc);
00584 ctrump_varray_init_pool(&ret->exprs, 4, sizeof(struct partial_bb_expr), &env->tmp_alloc);
00585 ctrump_varray_init_pool(&ret->dfs, 4, sizeof(struct partial_bb*), &env->tmp_alloc);
00586 ctrump_varray_init_pool(&ret->children, 4, sizeof(struct partial_bb*), &env->tmp_alloc);
00587
00588 ctrump_varray_init_pool(&ret->refs, 4, sizeof(struct ctrump_var_ref), &env->tmp_alloc);
00589 ctrump_varray_init_pool(&ret->stores, 4, sizeof(struct ctrump_var_store), &env->tmp_alloc);
00590
00591 ctrump_varray_init_pool(&ret->arr_loads, 4, sizeof(struct ctrump_memory_load), &env->tmp_alloc);
00592 ctrump_varray_init_pool(&ret->arr_stores, 4, sizeof(struct ctrump_memory_store), &env->tmp_alloc);
00593 ctrump_varray_init_pool(&ret->ordered_load_store, 4, sizeof(struct ordered_load_store_node), &env->tmp_alloc);
00594 ctrump_varray_init_pool(&ret->ordered_mem_load_store, 4, sizeof(struct ctrump_ordered_memory_load_store_node), &env->tmp_alloc);
00595
00596 ret->phi_inserted = NULL;
00597 ret->loop_cfg = loop;
00598 ret->flags = 0;
00599
00600 VA_PUSH_P(struct partial_bb*, &env->basic_blocks, ret, &env->tmp_alloc);
00601
00602 env->next_id++;
00603
00604 return ret;
00605 }
00606
00612 static struct partial_bb *
00613 get_id_bb(struct build_cfg_env *env,
00614 struct ctrump_stmt *stmt,
00615 struct ctrump_loop_cfg_info *cur_loop)
00616 {
00617 int id = stmt->id;
00618 struct partial_bb *ret = env->stmt_bb_table[id];
00619
00620 if (ret) {
00621 return ret;
00622 }
00623
00624 ret = new_bb(env, cur_loop);
00625
00626 env->stmt_bb_table[id] = ret;
00627
00628 return ret;
00629 }
00630
00637 static struct partial_bb *
00638 get_id_bb_maybe(struct build_cfg_env *env,
00639 struct ctrump_stmt *stmt,
00640 struct ctrump_loop_cfg_info *loop,
00641 struct partial_bb *return_to_bb)
00642 {
00643 if (stmt) {
00644 return get_id_bb(env, stmt, loop);
00645 } else {
00646 return return_to_bb;
00647 }
00648 }
00649
00650
00651
00652 static int
00653 build_cfg_stmt(struct ctrump_stmt *stmt,
00654 struct ctrump_stmt *next_stmt,
00655 struct build_cfg_env *env,
00656 const struct flow_env *flow_env,
00657 struct partial_bb **current_bb_ptr);
00658
00662 static int
00663 build_cfg_compound(const struct ctrump_compound_stmt *stmts,
00664 struct build_cfg_env *env,
00665 const struct flow_env *flow_env,
00666 struct partial_bb **current_bb_ptr,
00667 struct ctrump_stmt *next_block_stmt
00668 )
00669 {
00670 int i, r;
00671 struct ctrump_stmt *items = stmts->items;
00672 int nitem = stmts->num_item;
00673
00674 for (i=0; i<nitem; i++) {
00675 struct ctrump_stmt *stmt = &items[i];
00676 struct ctrump_stmt *next_stmt;
00677
00678 if (i < nitem-1) {
00679 next_stmt = &items[i+1];
00680 } else {
00681 next_stmt = next_block_stmt;
00682 }
00683
00684 r = build_cfg_stmt(stmt, next_stmt, env, flow_env, current_bb_ptr);
00685 if (r < 0)
00686 return r;
00687 }
00688
00689 return 0;
00690 }
00691
00696 static int
00697 dfs_order(struct partial_bb *start,
00698 struct build_cfg_env *env,
00699 int num_bb,
00700 ctrump_bitmap_t bb_bitmap)
00701 {
00702
00703 struct partial_bb **stack;
00704 int stk_size=1;
00705 ctrump_bitmap_t visited = bb_bitmap;
00706 int order = 0;
00707
00708 stack = ctrump_mempool_alloc(&env->tmp_alloc, num_bb*sizeof(struct partial_bb*));
00709 env->dfs_order = ctrump_mempool_alloc(&env->tmp_alloc, num_bb*sizeof(struct partial_bb*));
00710
00711 stack[0] = start;
00712 BMP_SET(visited, 0);
00713
00714 while (stk_size) {
00715 struct partial_bb *top;
00716 struct partial_bb *succ;
00717 int i, n;
00718 next:
00719 top = stack[stk_size-1];
00720 n = top->succs.nelem;
00721
00722 for (i=0; i<n; i++) {
00723 int id;
00724 succ = VA_ELEM(struct partial_bb *, &top->succs, i);
00725 id = succ->id;
00726
00727 if (BMP_P(visited,id) == 0) {
00728 succ->idom = top;
00729 BMP_SET(visited, id);
00730 stack[stk_size] = succ;
00731 stk_size++;
00732 goto next;
00733 }
00734 }
00735
00736 top->order = order;
00737 env->dfs_order[order] = top;
00738 order++;
00739 stk_size--;
00740 }
00741
00742 return order;
00743 }
00744
00748 static struct partial_bb *
00749 nca(struct partial_bb *x,
00750 struct partial_bb *y)
00751 {
00752 while (x != y) {
00753 int xo, yo;
00754 xo = x->order;
00755 yo = y->order;
00756
00757 if (xo < yo) {
00758 x = x->idom;
00759 xo = x->order;
00760 } else {
00761 y = y->idom;
00762 yo = y->order;
00763 }
00764 }
00765
00766 return x;
00767 }
00768
00772 static void
00773 build_dom(struct build_cfg_env *env,
00774 int num_bb)
00775 {
00776 int changed = 1;
00777 int i, j;
00778
00779 while (changed) {
00780 changed = 0;
00781 for (i=num_bb-1; i>=0; i--) {
00782 struct partial_bb *bb = env->dfs_order[i];
00783 int n = bb->preds.nelem;
00784 struct partial_bb *idom = bb->idom;
00785 for (j=0; j<n; j++) {
00786 struct partial_bb *new_idom;
00787 struct partial_bb *pred = VA_ELEM(struct partial_bb *, &bb->preds, j);
00788 new_idom = nca(idom, pred);
00789 if (idom != new_idom) {
00790 bb->idom = new_idom;
00791 idom = new_idom;
00792 changed = 1;
00793 }
00794 }
00795 }
00796 }
00797
00798
00799 for (i=0; i<num_bb-1; i++) {
00800 struct partial_bb *bb = env->dfs_order[i];
00801 struct partial_bb *idom = bb->idom;
00802
00803 VA_PUSH_P(struct partial_bb*, &idom->children, bb, &env->tmp_alloc);
00804 }
00805 }
00806
00810 static void
00811 find_df(struct build_cfg_env *env,
00812 int num_bb)
00813 {
00814 int i;
00815 for (i=0; i<num_bb; i++) {
00816 struct partial_bb *bb = env->dfs_order[i];
00817 struct partial_bb *succ, *child, *df;
00818 int i, n;
00819 n = bb->succs.nelem;
00820 for (i=0; i<n; i++) {
00821 succ = VA_ELEM(struct partial_bb *, &bb->succs, i);
00822 if (succ->idom != bb) {
00823 VA_PUSH_P(struct partial_bb *, &bb->dfs, succ, &env->tmp_alloc);
00824 }
00825 }
00826
00827 n = bb->children.nelem;
00828 for (i=0; i<n; i++) {
00829 int j, m;
00830 child = VA_ELEM(struct partial_bb *, &bb->children, i);
00831 m = child->dfs.nelem;
00832 for (j=0; j<m; j++) {
00833 df = VA_ELEM(struct partial_bb *, &child->dfs, j);
00834 if (df->idom != bb) {
00835 VA_PUSH_P(struct partial_bb *, &bb->dfs, df, &env->tmp_alloc);
00836 }
00837 }
00838 }
00839 }
00840 }
00841
00842
00847 static int
00848 insert_phi(struct partial_bb **bbs,
00849 int num_bb,
00850 struct partial_var_info *var_info,
00851 int num_var_info,
00852 int id,
00853 ctrump_bitmap_t tmp_bitmap,
00854 struct ctrump_mempool *cfg_alloc)
00855 {
00856 int i,j;
00857
00858 for (i=0; i<num_var_info; i++) {
00859 ctrump_bitmap_t modified_at = var_info[i].modified_at;
00860
00861 while (1) {
00862
00863 struct partial_bb *m_bb, **dfs;
00864 int m_bb_idx = ctrump_bitmap_ffs(modified_at, num_bb), num_df;
00865
00866 if (m_bb_idx < 0)
00867 break;
00868
00869 ctrump_bitmap_clear(modified_at, m_bb_idx);
00870 m_bb = bbs[m_bb_idx];
00871
00872 num_df = m_bb->dfs.nelem;
00873 dfs = m_bb->dfs.elements;
00874
00875 for (j=0; j<num_df; j++) {
00876 struct partial_bb *df_bb = dfs[j];
00877 if (ctrump_bitmap_p(df_bb->live, i) &&
00878 (! ctrump_bitmap_p(df_bb->phi_inserted, i)))
00879 {
00880 ctrump_bitmap_set(df_bb->phi_inserted, i);
00881 ctrump_bitmap_set(modified_at, df_bb->order);
00882 }
00883 }
00884 }
00885 }
00886
00887 for (i=0; i<num_bb; i++) {
00888
00889 struct partial_bb *bb = bbs[i];
00890 int num_phi = ctrump_bitmap_popcnt(bb->phi_inserted, num_var_info);
00891 int num_pred = bb->preds.nelem;
00892
00893 ctrump_bitmap_copy(tmp_bitmap, bb->phi_inserted, num_var_info);
00894
00895 bb->phi_nodes = ctrump_mempool_alloc(cfg_alloc, sizeof(struct ctrump_phi_node)*num_phi);
00896 for (j=0; j<num_phi; j++) {
00897 int var_idx = ctrump_bitmap_ffs(tmp_bitmap, num_var_info);
00898 ctrump_bitmap_clear(tmp_bitmap, var_idx);
00899
00900 bb->phi_nodes[j].id = id++;
00901 bb->phi_nodes[j].num_merge = num_pred;
00902 bb->phi_nodes[j].var_index = var_idx;
00903 bb->phi_nodes[j].nodes = ctrump_mempool_alloc(cfg_alloc, sizeof(struct ctrump_pdg_node*)*num_pred);
00904 }
00905 bb->num_phi = num_phi;
00906 }
00907
00908 return id;
00909 }
00910
00914 static struct ctrump_pdg_node *
00915 alloc_pdg_node(struct ctrump_varray *pdg_node_list,
00916 struct ctrump_mempool *alloc,
00917 struct ctrump_stmt *at,
00918 int *id,
00919 enum ctrump_pdg_node_code code)
00920 {
00921 struct ctrump_pdg_node *pdg = ctrump_mempool_alloc(alloc, sizeof(*pdg));
00922 pdg->code = code;
00923 pdg->id = (*id)++;
00924 pdg->at = at;
00925 VA_PUSH(struct ctrump_pdg_node*,pdg_node_list, pdg);
00926 return pdg;
00927 }
00928
00932 static int
00933 recog_reductive(struct ctrump_expr *e,
00934 struct ctrump_var *v,
00935 int is_float,
00936 enum ctrump_reductive_expr_code *ret_code,
00937 struct ctrump_expr **ret_expr)
00938 {
00939 tailcall:
00940 switch (e->code) {
00941 case CTRUMP_EXPR_BIN_ASSIGN:
00942 case CTRUMP_EXPR_BIN_COMMA:
00943 e = e->u.binary.rhs;
00944 goto tailcall;
00945
00946 case CTRUMP_CASE_BIN_ARITH_EXPR:
00947 case CTRUMP_CASE_BIN_EQ_EXPR:
00948 case CTRUMP_CASE_BIN_OP_ASSIGN_EXPR:
00949 case CTRUMP_CASE_BIN_LOG_EXPR:
00950 {
00951
00952
00953
00954 struct ctrump_expr *l=e->u.binary.lhs, *r=e->u.binary.rhs;
00955
00956 if (l->code == CTRUMP_EXPR_VARREF &&
00957 l->u.varref.var == v) {
00958
00959
00960 if (ctrump_expr_occur_var(r, v)) {
00961
00962 return 0;
00963 }
00964
00965 #define REDUC_CASE_LHS(ecode,rcode,r) \
00966 case ecode: \
00967 *ret_code = rcode; \
00968 *ret_expr = r; \
00969 return 1;
00970
00971 if (is_float) {
00972 switch (e->code) {
00973 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_ADD, CTRUMP_REDUCTIVE_FADD, r);
00974 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_SUB, CTRUMP_REDUCTIVE_FSUB, r);
00975 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_MUL, CTRUMP_REDUCTIVE_FMUL, r);
00976
00977 default:
00978 return 0;
00979 }
00980 } else {
00981 switch (e->code) {
00982 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_ADD, CTRUMP_REDUCTIVE_ADD, r);
00983 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_SUB, CTRUMP_REDUCTIVE_SUB, r);
00984 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_MUL, CTRUMP_REDUCTIVE_MUL, r);
00985 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_LOR, CTRUMP_REDUCTIVE_LOR, r);
00986 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_LAND, CTRUMP_REDUCTIVE_LAND, r);
00987 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BOR, CTRUMP_REDUCTIVE_BOR, r);
00988 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BAND, CTRUMP_REDUCTIVE_BAND, r);
00989 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BXOR, CTRUMP_REDUCTIVE_BXOR, r);
00990
00991 default:
00992 return 0;
00993 }
00994 }
00995 } else if (r->code == CTRUMP_EXPR_VARREF &&
00996 r->u.varref.var == v) {
00997
00998
00999 if (ctrump_expr_occur_var(l,v)) {
01000 return 0;
01001 }
01002
01003 if (is_float) {
01004 switch (e->code) {
01005 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_ADD, CTRUMP_REDUCTIVE_FADD, l);
01006 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_SUB, CTRUMP_REDUCTIVE_FSUB, l);
01007 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_MUL, CTRUMP_REDUCTIVE_FMUL, l);
01008
01009 default:
01010 return 0;
01011 }
01012 } else {
01013 switch (e->code) {
01014 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_ADD, CTRUMP_REDUCTIVE_ADD, l);
01015 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_SUB, CTRUMP_REDUCTIVE_SUB, l);
01016 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_MUL, CTRUMP_REDUCTIVE_MUL, l);
01017 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_LOR, CTRUMP_REDUCTIVE_LOR, r);
01018 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_LAND, CTRUMP_REDUCTIVE_LAND, r);
01019 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BOR, CTRUMP_REDUCTIVE_BOR, l);
01020 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BAND, CTRUMP_REDUCTIVE_BAND, l);
01021 REDUC_CASE_LHS(CTRUMP_EXPR_BIN_BXOR, CTRUMP_REDUCTIVE_BXOR, l);
01022
01023 default:
01024 return 0;
01025 }
01026 }
01027 } else {
01028 return 0;
01029 }
01030 return 0;
01031 }
01032
01033 case CTRUMP_EXPR_PAREN:
01034 e = e->u.paren.expr;
01035 goto tailcall;
01036
01037 case CTRUMP_EXPR_MACRO_EXPAND:
01038 e = e->u.macro_expand.expanded;
01039 goto tailcall;
01040
01041
01042 case CTRUMP_EXPR_ARRREF:
01043 case CTRUMP_EXPR_MEMBER_REF:
01044 case CTRUMP_EXPR_PTR_MEMBER_REF:
01045 case CTRUMP_EXPR_UNA_PTRREF:
01046 case CTRUMP_EXPR_UNA_POS:
01047 case CTRUMP_EXPR_UNA_NEG:
01048 case CTRUMP_EXPR_UNA_BCMPL:
01049 case CTRUMP_EXPR_UNA_LNEG:
01050 case CTRUMP_EXPR_UNA_ADDR:
01051 case CTRUMP_EXPR_CALL:
01052 case CTRUMP_EXPR_VARREF:
01053 case CTRUMP_CASE_CONSTANT_TERM:
01054 case CTRUMP_EXPR_EMPTY:
01055 case CTRUMP_EXPR_CONDITIONAL:
01056 case CTRUMP_EXPR_INITIALIZER:
01057 return 0;
01058
01059 case CTRUMP_EXPR_CAST:
01060 case CTRUMP_EXPR_IMPLICIT_CAST:
01061
01062
01063
01064
01065 return 0;
01066
01067 case CTRUMP_EXPR_TEXT:
01068 case CTRUMP_EXPR_IVTMP:
01069
01070 case CTRUMP_EXPR_UNA_PRE_INC:
01071 case CTRUMP_EXPR_UNA_PRE_DEC:
01072 case CTRUMP_EXPR_UNA_POST_INC:
01073 case CTRUMP_EXPR_UNA_POST_DEC:
01074
01075 ctrump_unreachable("invalid expr code");
01076 }
01077
01078 return 0;
01079 }
01080
01084 static struct ctrump_pdg_node *
01085 ssa_node_store_expr(enum ctrump_expr_code op_code,
01086 struct ctrump_var *var,
01087 struct ctrump_expr *store_val,
01088 struct ctrump_varray *pdg_node_list,
01089 struct ctrump_pdg_node *old_val,
01090 struct ctrump_stmt *at,
01091 struct ctrump_mempool *alloc,
01092 int *id)
01093 {
01094 struct ctrump_pdg_node *pdg;
01095 struct ctrump_expr *reduc_val;
01096 enum ctrump_reductive_expr_code reduc_op;
01097 struct ctrump_texpr *t = store_val->type;
01098 int is_float = ctrump_type_is_float(t);
01099 int is_reduc;
01100 enum ctrump_incremental_expr_code incr_code;
01101
01102 switch (op_code) {
01103 case CTRUMP_EXPR_UNA_PRE_INC:
01104 case CTRUMP_EXPR_UNA_PRE_DEC:
01105 case CTRUMP_EXPR_UNA_POST_INC:
01106 case CTRUMP_EXPR_UNA_POST_DEC:
01107 pdg = alloc_pdg_node(pdg_node_list, alloc, at, id, CTRUMP_PDG_VALUE_INCREMENTAL);
01108 pdg->u.incr.prev_val = old_val;
01109
01110 if (is_float) {
01111 switch(op_code) {
01112 case CTRUMP_EXPR_UNA_POST_INC:
01113 case CTRUMP_EXPR_UNA_PRE_INC:
01114 incr_code = CTRUMP_PDG_FINC;
01115 break;
01116
01117 case CTRUMP_EXPR_UNA_PRE_DEC:incr_code = CTRUMP_PDG_FDEC;
01118 case CTRUMP_EXPR_UNA_POST_DEC:
01119 incr_code = CTRUMP_PDG_FDEC;
01120 break;
01121
01122 default:
01123 ctrump_unreachable("incr op");
01124 }
01125 } else {
01126 switch(op_code) {
01127 case CTRUMP_EXPR_UNA_POST_INC:
01128 case CTRUMP_EXPR_UNA_PRE_INC:
01129 incr_code = CTRUMP_PDG_INC;
01130 break;
01131
01132 case CTRUMP_EXPR_UNA_PRE_DEC:incr_code = CTRUMP_PDG_DEC;
01133 case CTRUMP_EXPR_UNA_POST_DEC:
01134 incr_code = CTRUMP_PDG_FDEC;
01135 break;
01136
01137 default:
01138 ctrump_unreachable("incr op");
01139 }
01140 }
01141 pdg->u.incr.op = incr_code;
01142 return pdg;
01143
01144 case CTRUMP_EXPR_BIN_ADD_ASSIGN:
01145 case CTRUMP_EXPR_BIN_SUB_ASSIGN:
01146 case CTRUMP_EXPR_BIN_MUL_ASSIGN:
01147 pdg = alloc_pdg_node(pdg_node_list, alloc, at, id, CTRUMP_PDG_VALUE_REDUCTION);
01148 pdg->u.reduction.value = store_val;
01149 pdg->u.reduction.prev_val = old_val;
01150 if (is_float) {
01151 switch (op_code) {
01152 case CTRUMP_EXPR_BIN_ADD_ASSIGN:
01153 reduc_op = CTRUMP_REDUCTIVE_FADD;
01154 break;
01155 case CTRUMP_EXPR_BIN_SUB_ASSIGN:
01156 reduc_op = CTRUMP_REDUCTIVE_FSUB;
01157 break;
01158 case CTRUMP_EXPR_BIN_MUL_ASSIGN:
01159 reduc_op = CTRUMP_REDUCTIVE_FMUL;
01160 break;
01161
01162 default:
01163 ctrump_unreachable("reduc op");
01164 }
01165 } else {
01166 switch (op_code) {
01167 case CTRUMP_EXPR_BIN_ADD_ASSIGN:
01168 reduc_op = CTRUMP_REDUCTIVE_ADD;
01169 break;
01170 case CTRUMP_EXPR_BIN_SUB_ASSIGN:
01171 reduc_op = CTRUMP_REDUCTIVE_SUB;
01172 break;
01173 case CTRUMP_EXPR_BIN_MUL_ASSIGN:
01174 reduc_op = CTRUMP_REDUCTIVE_MUL;
01175 break;
01176
01177 default:
01178 ctrump_unreachable("reduc op");
01179 }
01180 }
01181 pdg->u.reduction.op = reduc_op;
01182 return pdg;
01183
01184 default:
01185 break;
01186 }
01187
01188 is_reduc = recog_reductive(store_val, var, is_float, &reduc_op, &reduc_val);
01189
01190 if (is_reduc) {
01191 pdg = alloc_pdg_node(pdg_node_list, alloc, at, id, CTRUMP_PDG_VALUE_REDUCTION);
01192 pdg->u.reduction.op = reduc_op;
01193 pdg->u.reduction.value = reduc_val;
01194 pdg->u.reduction.prev_val = old_val;
01195 } else {
01196 pdg = alloc_pdg_node(pdg_node_list, alloc, at, id, CTRUMP_PDG_VALUE_EXPR);
01197 pdg->u.expr.val = store_val;
01198 pdg->u.expr.store_op = op_code;
01199 }
01200
01201 return pdg;
01202 }
01203
01204
01209 static int
01210 assign_pdg_node_bb(struct ctrump_varray *pdg_node_list,
01211 struct partial_bb *bb,
01212 struct partial_var_info *var_info,
01213 int num_var_info,
01214 int id, struct ctrump_mempool *cfg_alloc)
01215 {
01216 int i,j,k;
01217 struct ordered_load_store_node *ls;
01218 struct ctrump_var_ref *refs = bb->refs.elements;
01219 struct ctrump_var_store *stores = bb->stores.elements;
01220 struct partial_bb **succs, **children;
01221 int num_ls, num_phi, num_succ, num_child;
01222 for (i=0; i<num_var_info; i++) {
01223 int depth = var_info[i].ssa_var_stack.nelem;
01224 VA_PUSH(int, &var_info[i].stack_depth, depth);
01225 }
01226
01227 num_phi = bb->num_phi;
01228 for (i=0; i<num_phi; i++) {
01229 struct ctrump_phi_node *n = &bb->phi_nodes[i];
01230 struct partial_var_info *vi = &var_info[n->var_index];
01231 struct ctrump_pdg_node *phi_pdg = alloc_pdg_node(pdg_node_list, cfg_alloc, NULL, &id, CTRUMP_PDG_VALUE_PHI);
01232
01233 phi_pdg->u.phi = n;
01234
01235 VA_PUSH(struct ctrump_pdg_node *, &vi->ssa_var_stack, phi_pdg);
01236 }
01237
01238 ls = bb->ordered_load_store.elements;
01239 num_ls = bb->ordered_load_store.nelem;
01240
01241 for (i=0; i<num_ls; i++) {
01242 struct ordered_load_store_node *n = &ls[i];
01243 struct partial_var_info *vi = &var_info[n->var_idx];
01244 struct ctrump_var_store *vs;
01245 struct ctrump_var_ref *vr;
01246 struct ctrump_pdg_node *pdg, *old_pdg;
01247
01248 switch (n->code) {
01249 case LOAD:
01250 pdg = VA_TOP(struct ctrump_pdg_node*, &vi->ssa_var_stack);
01251 vr = &refs[n->op_idx];
01252 vr->ref_expr->u.varref.pdg = pdg;
01253 break;
01254
01255 case STORE:
01256 vs = &stores[n->op_idx];
01257 old_pdg = VA_TOP(struct ctrump_pdg_node*, &vi->ssa_var_stack);
01258
01259 pdg = ssa_node_store_expr(vs->store_op, vs->var, vs->val, pdg_node_list, old_pdg, vs->at, cfg_alloc, &id);
01260
01261 vs->new_val = pdg;
01262 VA_PUSH(struct ctrump_pdg_node*, &vi->ssa_var_stack, pdg);
01263 break;
01264
01265 case INIT:
01266 ctrump_fixme("init");
01267 break;
01268 }
01269 }
01270
01271 succs = bb->succs.elements;
01272 num_succ = bb->succs.nelem;
01273
01274
01275 for (i=0; i<num_succ; i++) {
01276 struct partial_bb *succ = succs[i];
01277 struct partial_bb **preds;
01278 struct ctrump_phi_node *phi_nodes;
01279
01280
01281 preds = succ->preds.elements;
01282 for (j=0; ;j++) {
01283 if (preds[j] == bb) {
01284 break;
01285 }
01286 }
01287
01288 phi_nodes = succ->phi_nodes;
01289 num_phi = succ->num_phi;
01290 for (k=0; k<num_phi; k++) {
01291 struct ctrump_phi_node *n = &phi_nodes[k];
01292 struct partial_var_info *vi = &var_info[n->var_index];
01293 struct ctrump_pdg_node *pdg = VA_TOP(struct ctrump_pdg_node *, &vi->ssa_var_stack);
01294 n->nodes[j] = pdg;
01295 }
01296 }
01297
01298 children = bb->children.elements;
01299 num_child = bb->children.nelem;
01300 for (i=0; i<num_child; i++) {
01301 id = assign_pdg_node_bb(pdg_node_list, children[i], var_info, num_var_info, id, cfg_alloc);
01302 }
01303
01304 for (i=0; i<num_var_info; i++) {
01305 int depth = VA_POP(int, &var_info[i].stack_depth);
01306 var_info[i].ssa_var_stack.nelem = depth;
01307 }
01308
01309 return id;
01310 }
01311
01316 static int
01317 assign_pdg_node(struct ctrump_varray *pdg_node_list,
01318 struct partial_bb *entry,
01319 struct partial_var_info *var_info,
01320 int num_var_info,
01321 int id,
01322 struct ctrump_mempool *cfg_alloc)
01323 {
01324 int i;
01325 for (i=0; i<num_var_info; i++) {
01326 enum ctrump_pdg_node_code code;
01327 struct ctrump_pdg_node *pdg;
01328
01329 ctrump_varray_init(&var_info[i].ssa_var_stack, 4, sizeof(struct ctrump_pdg_node*));
01330 ctrump_varray_init(&var_info[i].stack_depth, 4, sizeof(int));
01331
01332 switch (var_info[i].result.var->stor_class) {
01333 case CTRUMP_STOR_CLASS_ARGMENT:
01334 code = CTRUMP_PDG_VALUE_ARG;
01335 break;
01336
01337 case CTRUMP_STOR_CLASS_STATIC:
01338 case CTRUMP_STOR_CLASS_EXTERN:
01339 case CTRUMP_STOR_CLASS_EXTDEF:
01340 code = CTRUMP_PDG_VALUE_GLOBAL;
01341 break;
01342
01343 default:
01344 code = CTRUMP_PDG_VALUE_UNINITIALIZED;
01345 break;
01346 }
01347
01348 pdg = alloc_pdg_node(pdg_node_list, cfg_alloc, NULL, &id, code);
01349 VA_PUSH(struct ctrump_pdg_node*, &var_info[i].ssa_var_stack, pdg);
01350 }
01351
01352 id = assign_pdg_node_bb(pdg_node_list, entry, var_info,
01353 num_var_info, id, cfg_alloc);
01354
01355 for (i=0; i<num_var_info; i++) {
01356 ctrump_varray_discard(&var_info[i].ssa_var_stack);
01357 ctrump_varray_discard(&var_info[i].stack_depth);
01358 }
01359
01360 return id;
01361 }
01362
01363 static int
01364 extract_load_store_expr_rval(struct ctrump_expr *e,
01365 struct ctrump_stmt *at,
01366 struct partial_bb *bb,
01367 struct ctrump_intmap *var_info_map,
01368 struct ctrump_build_cfg_error *error,
01369 struct ctrump_mempool *cfg_alloc,
01370 struct ctrump_mempool *tmp_alloc);
01371
01372 #define CHECK_ERROR(e) {int r = (e); if (r < 0) return r;}
01373
01377 static struct ctrump_subscript *
01378 append_nd_subscript(struct ctrump_varray *subscripts,
01379 struct ctrump_varray *nd_subscripts,
01380 struct ctrump_subscript *s,
01381 struct ctrump_texpr *load_data_texpr,
01382 struct ctrump_expr *subscript,
01383 struct ctrump_mempool *cfg_alloc)
01384 {
01385 struct ctrump_subscript_nd *nds;
01386
01387 if (ctrump_is_scalar_type(load_data_texpr)) {
01388 if (nd_subscripts->nelem == 0) {
01389
01390 } else {
01391 s->num_nd_subscript = nd_subscripts->nelem;
01392 s->nd_subscripts = ctrump_varray_copy(nd_subscripts, cfg_alloc);
01393
01394 VA_NEWELEM(subscripts);
01395 s = VA_LAST_PTR(struct ctrump_subscript, subscripts);
01396 }
01397
01398 nd_subscripts->nelem = 0;
01399
01400 VA_NEWELEM(nd_subscripts);
01401 nds = VA_LAST_PTR(struct ctrump_subscript_nd, nd_subscripts);
01402 nds->code = CTRUMP_SUBSCRIPT_TERMINAL;
01403 nds->u.terminal.expr = subscript;
01404 nds->u.terminal.load_type = load_data_texpr;
01405 } else if (load_data_texpr->code == CTRUMP_TYPE_UNION ||
01406 load_data_texpr->code == CTRUMP_TYPE_STRUCT) {
01407 VA_NEWELEM(nd_subscripts);
01408 nds = VA_LAST_PTR(struct ctrump_subscript_nd, nd_subscripts);
01409
01410 nds->code = CTRUMP_SUBSCRIPT_LOAD_RECORD;
01411 nds->u.load_record.load_type = load_data_texpr;
01412 nds->u.load_record.expr = subscript;
01413 } else {
01414 VA_NEWELEM(nd_subscripts);
01415 nds = VA_LAST_PTR(struct ctrump_subscript_nd, nd_subscripts);
01416
01417 nds->code = CTRUMP_SUBSCRIPT_COEF_ARRAY;
01418 nds->u.array_coef.coef = load_data_texpr->u.array.size;
01419 nds->u.array_coef.expr = subscript;
01420 }
01421
01422 return s;
01423 }
01424
01428 static struct ctrump_subscript *
01429 append_record_member_ref(struct ctrump_varray *subscripts,
01430 struct ctrump_varray *nd_subscripts,
01431 struct ctrump_subscript *s,
01432 struct ctrump_member_ref *ref,
01433 struct ctrump_texpr *load_data_type,
01434 int is_pointer,
01435 struct ctrump_mempool *cfg_alloc)
01436 {
01437 struct ctrump_subscript_nd *nds;
01438 struct ctrump_texpr *type;
01439 VA_NEWELEM(nd_subscripts);
01440 nds = VA_LAST_PTR(struct ctrump_subscript_nd, nd_subscripts);
01441
01442 type = ref->obj_expr->type;
01443 if (is_pointer) {
01444 type = ctrump_retrieve_pointer_type(type);
01445 assert(type);
01446 }
01447
01448 if (ctrump_is_scalar_type(load_data_type)) {
01449 nds->code = CTRUMP_SUBSCRIPT_RECORD_MEMBER_TERMINAL;
01450 nds->u.record_member_terminal.member_name = ref->member_name;
01451 nds->u.record_member_terminal.record_type = type;
01452 nds->u.record_member_terminal.load_type = load_data_type;
01453 } else {
01454 nds->code = CTRUMP_SUBSCRIPT_RECORD_MEMBER;
01455 nds->u.record_member.member_name = ref->member_name;
01456 nds->u.record_member.record_type = type;
01457 }
01458
01459 return s;
01460 }
01461
01465 static int
01466 recog_array_access(struct ctrump_expr **ret_array,
01467 struct ctrump_subscript **ret_vec,
01468 int *num_ret,
01469 struct ctrump_expr *access_expr,
01470 struct partial_bb *bb,
01471 struct ctrump_intmap *var_info_map,
01472 struct ctrump_build_cfg_error *error,
01473 struct ctrump_stmt *at,
01474 struct ctrump_mempool *cfg_alloc,
01475 struct ctrump_mempool *tmp_alloc)
01476 {
01477 struct ctrump_subscript *ret;
01478 struct ctrump_expr *peeled_array;
01479
01480
01481 struct ctrump_subscript *subscript_elems;
01482 struct ctrump_subscript *s;
01483 struct ctrump_varray subscripts;
01484 struct ctrump_varray nd_subscripts;
01485 struct ctrump_expr *array, *subscript;
01486 int i, n;
01487
01488 ctrump_varray_init(&subscripts, 4, sizeof(struct ctrump_subscript));
01489 ctrump_varray_init(&nd_subscripts, 4, sizeof(struct ctrump_subscript_nd));
01490
01491 VA_NEWELEM(&subscripts);
01492 s = VA_LAST_PTR(struct ctrump_subscript, &subscripts);
01493
01494 array = access_expr;
01495
01496 while (1) {
01497 struct ctrump_texpr *array_texpr;
01498 enum ctrump_expr_code expr_code;
01499 peeled_array = ctrump_peel_cast_to_pointer_from_array(array);
01500 array_texpr = peeled_array->type;
01501 array_texpr = ctrump_get_unqualified_type(array_texpr);
01502
01503 expr_code = peeled_array->code;
01504
01505 switch (expr_code) {
01506 case CTRUMP_EXPR_ARRREF:
01507 subscript = peeled_array->u.arr_ref.subscript;
01508
01509 CHECK_ERROR(extract_load_store_expr_rval(subscript, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01510 s = append_nd_subscript(&subscripts, &nd_subscripts,
01511 s, array_texpr,
01512 subscript, cfg_alloc);
01513
01514 array = peeled_array->u.arr_ref.array;
01515 break;
01516
01517 case CTRUMP_EXPR_PTR_MEMBER_REF:
01518 s = append_record_member_ref(&subscripts, &nd_subscripts,
01519 s, &peeled_array->u.member_ref, array_texpr, 1, cfg_alloc);
01520
01521 peeled_array = ctrump_peel_cast_to_pointer_from_array(peeled_array);
01522 array_texpr = peeled_array->type;
01523 array_texpr = ctrump_get_unqualified_type(array_texpr);
01524 s = append_nd_subscript(&subscripts, &nd_subscripts,
01525 s, array_texpr,
01526 NULL, cfg_alloc);
01527
01528 array = peeled_array->u.member_ref.obj_expr;
01529 break;
01530
01531 case CTRUMP_EXPR_MEMBER_REF:
01532 s = append_record_member_ref(&subscripts, &nd_subscripts,
01533 s, &peeled_array->u.member_ref, array_texpr, 0, cfg_alloc);
01534 array = peeled_array->u.member_ref.obj_expr;
01535 break;
01536
01537 case CTRUMP_EXPR_UNA_PTRREF:
01538 s = append_nd_subscript(&subscripts, &nd_subscripts,
01539 s, array_texpr,
01540 NULL, cfg_alloc);
01541 array = peeled_array->u.unary.expr;
01542 break;
01543
01544 default:
01545 array = peeled_array;
01546 goto end;
01547 }
01548 }
01549 end:
01550
01551 s->num_nd_subscript = nd_subscripts.nelem;
01552 s->nd_subscripts = ctrump_varray_close(&nd_subscripts, cfg_alloc);
01553
01554 n = subscripts.nelem;
01555 subscript_elems = subscripts.elements;
01556 ret = ctrump_mempool_alloc(cfg_alloc, sizeof(*ret)*n);
01557
01558 for (i=0; i<n; i++) {
01559 ret[i] = subscript_elems[i];
01560 }
01561
01562 *num_ret = n;
01563 *ret_vec = ret;
01564
01565 ctrump_varray_discard(&subscripts);
01566
01567 *ret_array = array;
01568 return 0;
01569 }
01570
01574 static void
01575 append_ordered_memop(struct ctrump_varray *memop,
01576 enum ctrump_load_store_t load_store,
01577 int idx, struct ctrump_mempool *tmp_alloc)
01578 {
01579 struct ctrump_ordered_memory_load_store_node *n;
01580 VA_NEWELEM_P(memop, tmp_alloc);
01581 n = VA_LAST_PTR(struct ctrump_ordered_memory_load_store_node, memop);
01582 n->code = load_store;
01583 n->op_index = idx;
01584 }
01585
01589 static int
01590 append_memory_store(struct ctrump_varray *store,
01591 struct ctrump_varray *ordered,
01592 struct partial_bb *bb,
01593 struct ctrump_intmap *var_info_map,
01594 struct ctrump_build_cfg_error *error,
01595 struct ctrump_stmt *at_stmt,
01596 enum ctrump_expr_code store_op,
01597 struct ctrump_expr *dest_expr,
01598 struct ctrump_expr *val,
01599 int flags,
01600 struct ctrump_mempool *cfg_alloc,
01601 struct ctrump_mempool *tmp_alloc)
01602 {
01603 int num_subscript;
01604 struct ctrump_subscript *subscript;
01605 struct ctrump_expr *array_expr;
01606 struct ctrump_memory_store *ms;
01607 int idx;
01608
01609 CHECK_ERROR(recog_array_access(&array_expr, &subscript, &num_subscript, dest_expr,
01610 bb, var_info_map, error, at_stmt, cfg_alloc, tmp_alloc));
01611
01612
01613 if (array_expr) {
01614 CHECK_ERROR(extract_load_store_expr_rval(array_expr, at_stmt, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01615 }
01616
01617 idx = store->nelem;
01618
01619 VA_NEWELEM_P(store, tmp_alloc);
01620 ms = VA_LAST_PTR(struct ctrump_memory_store, store);
01621 ms->mem_access.at_stmt = at_stmt;
01622 ms->mem_access.at_expr = dest_expr;
01623
01624 ms->mem_access.array = array_expr;
01625 ms->mem_access.subscripts = subscript;
01626 ms->mem_access.num_subscript = num_subscript;
01627 ms->mem_access.flags = flags;
01628 ms->val = val;
01629 ms->store_op = store_op;
01630
01631 append_ordered_memop(ordered, CTRUMP_MEMORY_STORE, idx, tmp_alloc);
01632
01633 return 0;
01634 }
01635
01639 static void
01640 add_var_loadstore(struct partial_bb *bb,
01641 enum load_store_t code,
01642 int op_idx,
01643 int var_idx,
01644 struct ctrump_mempool *tmp_alloc)
01645 {
01646 struct ordered_load_store_node *n;
01647 VA_NEWELEM_P(&bb->ordered_load_store, tmp_alloc);
01648 n = VA_LAST_PTR(struct ordered_load_store_node, &bb->ordered_load_store);
01649 n->code = code;
01650 n->op_idx = op_idx;
01651 n->var_idx = var_idx;
01652 }
01653
01657 static void
01658 add_var_store(struct partial_bb *bb,
01659 struct partial_var_info *vi,
01660 struct ctrump_varray *stores,
01661 struct ctrump_stmt *at,
01662 struct ctrump_var *var,
01663 struct ctrump_expr *var_ref_expr,
01664 struct ctrump_expr *val_expr,
01665 struct ctrump_pdg_node *pdg,
01666 enum ctrump_expr_code store_op,
01667 int flags,
01668 struct ctrump_mempool *tmp_alloc,
01669 enum load_store_t store_code)
01670 {
01671 struct ctrump_var_store *d;
01672 int op_idx = stores->nelem;
01673 VA_NEWELEM_P(stores, tmp_alloc);
01674 d = VA_LAST_PTR(struct ctrump_var_store, stores);
01675 d->at = at;
01676 d->var = var;
01677 d->val = val_expr;
01678 d->store_op = store_op;
01679 d->flags = flags;
01680 d->var_ref = var_ref_expr;
01681
01682 ctrump_bitmap_set(bb->kill, vi->result.index);
01683 ctrump_bitmap_set(vi->modified_at, bb->order);
01684
01685 add_var_loadstore(bb, store_code, op_idx, vi->result.index, tmp_alloc);
01686 }
01687
01688
01692 static int
01693 extract_load_store_assign(enum ctrump_expr_code store_op,
01694 struct ctrump_expr *lhs,
01695 struct ctrump_expr *val_expr,
01696 struct ctrump_stmt *at,
01697 struct partial_bb *bb,
01698 struct ctrump_intmap *var_info_map,
01699 struct ctrump_build_cfg_error *error,
01700 struct ctrump_mempool *cfg_alloc,
01701 struct ctrump_mempool *tmp_alloc)
01702 {
01703 int found;
01704 int flags = 0;
01705 struct partial_var_info *vi;
01706
01707 struct ctrump_varray *stores = &bb->stores;
01708 struct ctrump_varray *mem_store = &bb->arr_stores;
01709 struct ctrump_varray *mem_ordered = &bb->ordered_mem_load_store;
01710
01711 lhs = ctrump_peel_paren(lhs);
01712
01713 switch (lhs->code) {
01714 case CTRUMP_EXPR_VARREF:
01715 vi = ctrump_intmap_lookup(var_info_map, &found, lhs->u.varref.var->id);
01716 assert(found);
01717
01718 add_var_store(bb, vi, stores, at, lhs->u.varref.var, lhs, val_expr,
01719 NULL, store_op, flags, tmp_alloc, STORE);
01720
01721 lhs->u.varref.pdg = NULL;
01722
01723 if (flags & CTRUMP_MEMORY_ACCESS_PARTIAL) {
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733 ctrump_bitmap_set(bb->use, vi->result.index);
01734 }
01735
01736 break;
01737
01738 case CTRUMP_EXPR_UNA_PTRREF:
01739 case CTRUMP_EXPR_ARRREF:
01740 case CTRUMP_EXPR_PTR_MEMBER_REF:
01741 case CTRUMP_EXPR_MEMBER_REF:
01742 CHECK_ERROR(append_memory_store(mem_store, mem_ordered, bb, var_info_map, error,
01743 at, store_op, lhs, val_expr, flags,
01744 cfg_alloc, tmp_alloc));
01745 break;
01746
01747 default:
01748 error->code = CTRUMP_BUILD_CFG_ERROR_INVALID_LVALUE;
01749 error->stmt = at;
01750 return -1;
01751 }
01752
01753 return 0;
01754 }
01755
01759 static int
01760 append_memory_load(struct ctrump_varray *aload,
01761 struct ctrump_varray *ordered,
01762 struct partial_bb *bb,
01763 struct ctrump_intmap *var_info_map,
01764 struct ctrump_build_cfg_error *error,
01765 struct ctrump_stmt *at_stmt,
01766 struct ctrump_expr *load_expr,
01767 struct ctrump_mempool *cfg_alloc,
01768 struct ctrump_mempool *tmp_alloc)
01769 {
01770 struct ctrump_memory_load *al;
01771 struct ctrump_subscript *subscripts;
01772 int num_subscript;
01773 int idx = aload->nelem;
01774 struct ctrump_expr *next_array_expr;
01775
01776 CHECK_ERROR(recog_array_access(&next_array_expr, &subscripts, &num_subscript, load_expr,
01777 bb, var_info_map, error, at_stmt, cfg_alloc, tmp_alloc));
01778 if (next_array_expr) {
01779 CHECK_ERROR(extract_load_store_expr_rval(next_array_expr, at_stmt, bb,
01780 var_info_map, error, cfg_alloc, tmp_alloc));
01781 }
01782
01783 VA_NEWELEM_P(aload, tmp_alloc);
01784 al = VA_LAST_PTR(struct ctrump_memory_load, aload);
01785 al->mem_access.subscripts = subscripts;
01786 al->mem_access.num_subscript = num_subscript;
01787 al->mem_access.flags = 0;
01788 al->mem_access.array = next_array_expr;
01789
01790 al->mem_access.at_stmt = at_stmt;
01791 al->mem_access.at_expr = load_expr;
01792
01793 append_ordered_memop(ordered, CTRUMP_MEMORY_LOAD, idx, tmp_alloc);
01794
01795 return 0;
01796 }
01797
01798 static int extract_load_store_initializer(struct ctrump_initializer *initializer,
01799 struct ctrump_stmt *at,
01800 struct partial_bb *bb,
01801 struct ctrump_intmap *var_info_map,
01802 struct ctrump_build_cfg_error *error,
01803 struct ctrump_mempool *cfg_alloc,
01804 struct ctrump_mempool *tmp_alloc);
01805
01809 static int
01810 extract_load_store_initializer_list(struct ctrump_initializer_list *init_list,
01811 struct ctrump_stmt *at,
01812 struct partial_bb *bb,
01813 struct ctrump_intmap *var_info_map,
01814 struct ctrump_build_cfg_error *error,
01815 struct ctrump_mempool *cfg_alloc,
01816 struct ctrump_mempool *tmp_alloc)
01817 {
01818 int i, j, n, m;
01819 n = init_list->num_elem;
01820 for (i=0; i<n; i++) {
01821 struct ctrump_initializer_list_elem *e = &init_list->elems[i];
01822
01823 m = e->num_designator;
01824
01825
01826 for (j=0; j<m; j++) {
01827
01828 struct ctrump_designator *d = &e->designators_list[j];
01829 switch (d->code) {
01830 case CTRUMP_DESIGNATOR_INDEX:
01831 CHECK_ERROR(extract_load_store_expr_rval(d->u.index.index,
01832 at, bb, var_info_map,
01833 error, cfg_alloc, tmp_alloc));
01834 break;
01835
01836 case CTRUMP_DESIGNATOR_IDENT:
01837
01838 break;
01839 }
01840 }
01841
01842 CHECK_ERROR(extract_load_store_initializer(&e->initializer,
01843 at, bb, var_info_map,
01844 error, cfg_alloc, tmp_alloc));
01845 }
01846
01847 return 0;
01848 }
01849
01853 static int
01854 extract_load_store_initializer(struct ctrump_initializer *initializer,
01855 struct ctrump_stmt *at,
01856 struct partial_bb *bb,
01857 struct ctrump_intmap *var_info_map,
01858 struct ctrump_build_cfg_error *error,
01859 struct ctrump_mempool *cfg_alloc,
01860 struct ctrump_mempool *tmp_alloc)
01861 {
01862 switch (initializer->code) {
01863 case CTRUMP_INITIALIZER_EXPR:
01864 CHECK_ERROR(extract_load_store_expr_rval(initializer->u.expr,
01865 at, bb, var_info_map,
01866 error, cfg_alloc, tmp_alloc));
01867 break;
01868
01869 case CTRUMP_INITIALIZER_NESTED:
01870 CHECK_ERROR(extract_load_store_initializer_list(initializer->u.nest,
01871 at, bb, var_info_map,
01872 error, cfg_alloc, tmp_alloc));
01873 break;
01874
01875 case CTRUMP_INITIALIZER_EMPTY:
01876 break;
01877 }
01878
01879 return 0;
01880 }
01881
01882
01883
01887 static int
01888 extract_load_store_expr_rval(struct ctrump_expr *e,
01889 struct ctrump_stmt *at,
01890 struct partial_bb *bb,
01891 struct ctrump_intmap *var_info_map,
01892 struct ctrump_build_cfg_error *error,
01893 struct ctrump_mempool *cfg_alloc,
01894 struct ctrump_mempool *tmp_alloc)
01895 {
01896 struct ctrump_varray *refs = &bb->refs;
01897 struct ctrump_varray *aload = &bb->arr_loads;
01898 struct ctrump_var_ref *u;
01899 struct ctrump_expr *una;
01900 struct ctrump_binary_expr *bin;
01901 struct partial_var_info *vi;
01902 int var_index, op_index, found;
01903 struct ctrump_varray *mem_ordered = &bb->ordered_mem_load_store;
01904 int i, n;
01905 struct ctrump_initializer_list *init_list;
01906
01907 tailcall:
01908 switch (e->code) {
01909 case CTRUMP_EXPR_VARREF:
01910 op_index = refs->nelem;
01911 VA_NEWELEM_P(refs, tmp_alloc);
01912 u = VA_LAST_PTR(struct ctrump_var_ref, refs);
01913 u->at = at;
01914 u->ref_expr = e;
01915
01916 vi = ctrump_intmap_lookup(var_info_map, &found, e->u.varref.var->id);
01917 var_index = vi->result.index;
01918 e->u.varref.pdg = NULL;
01919
01920 add_var_loadstore(bb, LOAD, op_index, var_index, tmp_alloc);
01921
01922 if (ctrump_bitmap_p(bb->kill, var_index) == 0) {
01923 ctrump_bitmap_set(bb->use, var_index);
01924 } else {
01925
01926 }
01927 break;
01928
01929 case CTRUMP_EXPR_CAST:
01930 e = e->u.cast.expr;
01931 goto tailcall;
01932
01933 case CTRUMP_EXPR_IMPLICIT_CAST:
01934 e = e->u.implicit_cast.expr;
01935 goto tailcall;
01936
01937 case CTRUMP_CASE_CONSTANT_TERM:
01938 case CTRUMP_EXPR_EMPTY:
01939 break;
01940
01941 case CTRUMP_EXPR_BIN_COMMA:
01942 case CTRUMP_EXPR_BIN_ADD:
01943 case CTRUMP_EXPR_BIN_SUB:
01944 case CTRUMP_EXPR_BIN_MUL:
01945 case CTRUMP_EXPR_BIN_DIV:
01946 case CTRUMP_EXPR_BIN_MOD:
01947 case CTRUMP_EXPR_BIN_BAND:
01948 case CTRUMP_EXPR_BIN_BOR:
01949 case CTRUMP_EXPR_BIN_BXOR:
01950 case CTRUMP_EXPR_BIN_LSHIFT:
01951 case CTRUMP_EXPR_BIN_RSHIFT:
01952 case CTRUMP_EXPR_BIN_GT:
01953 case CTRUMP_EXPR_BIN_GE:
01954 case CTRUMP_EXPR_BIN_LT:
01955 case CTRUMP_EXPR_BIN_LE:
01956 case CTRUMP_EXPR_BIN_EQ:
01957 case CTRUMP_EXPR_BIN_NE:
01958 bin = &e->u.binary;
01959 CHECK_ERROR(extract_load_store_expr_rval(bin->lhs, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01960 e = bin->rhs;
01961 goto tailcall;
01962
01963 case CTRUMP_EXPR_BIN_ASSIGN:
01964 bin = &e->u.binary;
01965 CHECK_ERROR(extract_load_store_expr_rval(bin->rhs, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01966 CHECK_ERROR(extract_load_store_assign(e->code, bin->lhs, bin->rhs,
01967 at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01968 break;
01969
01970 case CTRUMP_CASE_BIN_OP_ASSIGN_EXPR:
01971 bin = &e->u.binary;
01972 CHECK_ERROR(extract_load_store_expr_rval(bin->lhs, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01973 CHECK_ERROR(extract_load_store_expr_rval(bin->rhs, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01974 CHECK_ERROR(extract_load_store_assign(e->code, bin->lhs, bin->rhs,
01975 at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01976 break;
01977
01978 case CTRUMP_EXPR_UNA_PRE_INC:
01979 case CTRUMP_EXPR_UNA_POST_INC:
01980 case CTRUMP_EXPR_UNA_PRE_DEC:
01981 case CTRUMP_EXPR_UNA_POST_DEC:
01982 una = e->u.unary.expr;
01983 CHECK_ERROR(extract_load_store_expr_rval(una, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01984 CHECK_ERROR(extract_load_store_assign(e->code, una, una,
01985 at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
01986 break;
01987
01988 case CTRUMP_EXPR_UNA_POS:
01989 case CTRUMP_EXPR_UNA_NEG:
01990 case CTRUMP_EXPR_UNA_BCMPL:
01991 case CTRUMP_EXPR_UNA_LNEG:
01992 e = e->u.unary.expr;
01993 goto tailcall;
01994
01995 case CTRUMP_EXPR_PAREN:
01996 e = e->u.paren.expr;
01997 goto tailcall;
01998
01999 case CTRUMP_EXPR_UNA_ADDR:
02000 e = e->u.unary.expr;
02001 addr_expr:
02002 switch (e->code) {
02003 case CTRUMP_EXPR_VARREF:
02004 e->u.varref.var->addressed = 1;
02005 e->u.varref.pdg = NULL;
02006 break;
02007
02008 case CTRUMP_EXPR_ARRREF:
02009
02010 CHECK_ERROR(extract_load_store_expr_rval(e->u.arr_ref.array, at, bb, var_info_map, error, cfg_alloc, tmp_alloc));
02011 e = e->u.arr_ref.subscript;
02012 goto tailcall;
02013
02014 case CTRUMP_EXPR_UNA_PTRREF:
02015
02016 e = e->u.unary.expr;
02017 goto tailcall;
02018
02019 case CTRUMP_EXPR_PAREN:
02020 e = e->u.paren.expr;
02021 goto addr_expr;
02022
02023 default:
02024 error->code = CTRUMP_BUILD_CFG_ERROR_INVALID_ADDRESSOP;
02025 error->stmt = at;
02026 return -1;
02027 }
02028 break;
02029
02030 case CTRUMP_CASE_BIN_LOG_EXPR:
02031
02032 bin = &e->u.binary;
02033 e = bin->lhs;
02034 goto tailcall;
02035
02036 case CTRUMP_EXPR_CONDITIONAL:
02037
02038 e = e->u.cond.cond;
02039 goto tailcall;
02040
02041 case CTRUMP_EXPR_CALL:
02042 n = e->u.call.num_args;
02043 for (i=0; i<n; i++) {
02044 CHECK_ERROR(extract_load_store_expr_rval(&e->u.call.args[i], at, bb, var_info_map,
02045 error, cfg_alloc, tmp_alloc));
02046 }
02047 e = e->u.call.func_expr;
02048 goto tailcall;
02049
02050 case CTRUMP_EXPR_UNA_PTRREF:
02051 case CTRUMP_EXPR_PTR_MEMBER_REF:
02052 case CTRUMP_EXPR_MEMBER_REF:
02053 case CTRUMP_EXPR_ARRREF:
02054 CHECK_ERROR(append_memory_load(aload, mem_ordered, bb, var_info_map, error, at,
02055 e, cfg_alloc, tmp_alloc));
02056 break;
02057
02058 case CTRUMP_EXPR_INITIALIZER:
02059 init_list = &e->u.initializer.initializer;
02060 CHECK_ERROR(extract_load_store_initializer_list(init_list, at, bb, var_info_map,
02061 error, cfg_alloc, tmp_alloc));
02062
02063 break;
02064
02065 case CTRUMP_EXPR_MACRO_EXPAND:
02066 ctrump_fixme("extract load store");
02067 break;
02068
02069 case CTRUMP_EXPR_TEXT:
02070 case CTRUMP_EXPR_IVTMP:
02071 ctrump_unreachable("invalid expr code");
02072 }
02073
02074 return 0;
02075 }
02076
02080 static int
02081 extract_load_store(struct partial_bb *bb,
02082 struct ctrump_intmap *var_info_map,
02083 struct ctrump_build_cfg_error *error,
02084 struct ctrump_mempool *cfg_alloc,
02085 struct ctrump_mempool *tmp_alloc)
02086 {
02087 int i, n;
02088 struct partial_bb_expr *el = (struct partial_bb_expr*)bb->exprs.elements;
02089
02090 n = bb->exprs.nelem;
02091
02092 for (i=0; i<n; i++) {
02093 switch (el[i].code) {
02094 case BB_EXPR:
02095 CHECK_ERROR(extract_load_store_expr_rval(el[i].u.expr,
02096 el[i].at,
02097 bb,
02098 var_info_map,
02099 error,
02100 cfg_alloc,
02101 tmp_alloc));
02102 break;
02103
02104 }
02105 }
02106
02107 return 0;
02108 }
02109
02113 static void
02114 assign_var_info_expr(struct ctrump_varray *info,
02115 struct ctrump_intmap *info_map,
02116 struct ctrump_expr *e,
02117 int num_bb,
02118 struct ctrump_mempool *tmp_alloc)
02119 {
02120 struct ctrump_binary_expr *bin;
02121 struct partial_var_info *vi;
02122 struct ctrump_var *v;
02123 struct ctrump_intmap_bucket *b;
02124 int found;
02125 int n, i;
02126
02127 tailcall:
02128 switch (e->code) {
02129 case CTRUMP_EXPR_VARREF:
02130 v = e->u.varref.var;
02131 b = ctrump_intmap_lookup_add(info_map, &found, v->id);
02132 if (found == 0) {
02133 int index = info->nelem;
02134 VA_NEWELEM_P(info, tmp_alloc);
02135 vi = VA_LAST_PTR(struct partial_var_info, info);
02136 vi->result.index = index;
02137 vi->result.var = v;
02138 vi->modified_at = zero_bmp(num_bb, tmp_alloc);
02139
02140 b->val = (void*)(intptr_t)index;
02141 }
02142 break;
02143
02144 case CTRUMP_EXPR_CAST:
02145 e = e->u.cast.expr;
02146 goto tailcall;
02147
02148 case CTRUMP_EXPR_IMPLICIT_CAST:
02149 e = e->u.implicit_cast.expr;
02150 goto tailcall;
02151
02152 case CTRUMP_EXPR_UNA_PTRREF:
02153 case CTRUMP_EXPR_UNA_POS:
02154 case CTRUMP_EXPR_UNA_NEG:
02155 case CTRUMP_EXPR_UNA_ADDR:
02156 case CTRUMP_EXPR_UNA_PRE_INC:
02157 case CTRUMP_EXPR_UNA_POST_INC:
02158 case CTRUMP_EXPR_UNA_PRE_DEC:
02159 case CTRUMP_EXPR_UNA_POST_DEC:
02160 case CTRUMP_EXPR_UNA_BCMPL:
02161 case CTRUMP_EXPR_UNA_LNEG:
02162 e = e->u.unary.expr;
02163 goto tailcall;
02164
02165 case CTRUMP_EXPR_PAREN:
02166 e = e->u.paren.expr;
02167 goto tailcall;
02168
02169 case CTRUMP_CASE_CONSTANT_TERM:
02170 case CTRUMP_EXPR_EMPTY:
02171 break;
02172
02173 case CTRUMP_CASE_BIN_EQ_EXPR:
02174 case CTRUMP_CASE_BIN_ARITH_EXPR:
02175 case CTRUMP_EXPR_BIN_ASSIGN:
02176 case CTRUMP_CASE_BIN_OP_ASSIGN_EXPR:
02177 case CTRUMP_EXPR_BIN_COMMA:
02178 bin = &e->u.binary;
02179 assign_var_info_expr(info, info_map, bin->lhs, num_bb, tmp_alloc);
02180 e = bin->rhs;
02181 goto tailcall;
02182
02183 case CTRUMP_EXPR_ARRREF:
02184 assign_var_info_expr(info, info_map, e->u.arr_ref.array, num_bb, tmp_alloc);
02185 e = e->u.arr_ref.subscript;
02186 goto tailcall;
02187
02188 case CTRUMP_CASE_BIN_LOG_EXPR:
02189
02190 bin = &e->u.binary;
02191 e = bin->lhs;
02192 goto tailcall;
02193
02194 case CTRUMP_EXPR_CONDITIONAL:
02195
02196 e = e->u.cond.cond;
02197 goto tailcall;
02198
02199 case CTRUMP_EXPR_CALL:
02200 n = e->u.call.num_args;
02201 for (i=0; i<n; i++) {
02202 assign_var_info_expr(info, info_map, &e->u.call.args[i],
02203 num_bb, tmp_alloc);
02204 }
02205 e = e->u.call.func_expr;
02206 goto tailcall;
02207
02208 case CTRUMP_EXPR_MEMBER_REF:
02209 case CTRUMP_EXPR_PTR_MEMBER_REF:
02210 e = e->u.member_ref.obj_expr;
02211 goto tailcall;
02212
02213 case CTRUMP_EXPR_INITIALIZER:
02214 ctrump_fixme("assign var info");
02215 break;
02216
02217 case CTRUMP_EXPR_MACRO_EXPAND:
02218 case CTRUMP_EXPR_TEXT:
02219 case CTRUMP_EXPR_IVTMP:
02220 ctrump_unreachable("invalid expr code");
02221 }
02222 }
02223
02224 static void assign_var_info_initializer(struct ctrump_varray *var_info_vec,
02225 struct ctrump_intmap *var_info_map,
02226 struct ctrump_initializer *initializer,
02227 int num_bb,
02228 struct ctrump_mempool *tmp_alloc);
02229
02233 static void
02234 assign_var_info_initializer_list(struct ctrump_varray *var_info_vec,
02235 struct ctrump_intmap *var_info_map,
02236 struct ctrump_initializer_list *inits,
02237 int num_bb, struct ctrump_mempool *tmp_alloc)
02238 {
02239 int i, j, n, m;
02240
02241 n = inits->num_elem;
02242 for (i=0; i<n; i++) {
02243 struct ctrump_initializer_list_elem *e = &inits->elems[i];
02244
02245 m = e->num_designator;
02246
02247 for (j=0; j<m; j++) {
02248 struct ctrump_designator *d = &e->designators_list[j];
02249 if (d->code == CTRUMP_DESIGNATOR_INDEX) {
02250 assign_var_info_expr(var_info_vec, var_info_map,
02251 d->u.index.index, num_bb, tmp_alloc);
02252 }
02253 }
02254
02255 assign_var_info_initializer(var_info_vec, var_info_map,
02256 &e->initializer, num_bb, tmp_alloc);
02257 }
02258 }
02259
02263 static void
02264 assign_var_info_initializer(struct ctrump_varray *var_info_vec,
02265 struct ctrump_intmap *var_info_map,
02266 struct ctrump_initializer *initializer,
02267 int num_bb,
02268 struct ctrump_mempool *tmp_alloc)
02269 {
02270 switch (initializer->code) {
02271 case CTRUMP_INITIALIZER_EXPR:
02272 assign_var_info_expr(var_info_vec, var_info_map,
02273 initializer->u.expr, num_bb, tmp_alloc);
02274 break;
02275
02276 case CTRUMP_INITIALIZER_NESTED:
02277 assign_var_info_initializer_list(var_info_vec, var_info_map,
02278 initializer->u.nest, num_bb, tmp_alloc);
02279 break;
02280
02281 case CTRUMP_INITIALIZER_EMPTY:
02282 break;
02283 }
02284 }
02285
02290 static int
02291 assign_var_info(struct partial_bb **bb_vec,
02292 int num_bb,
02293 struct ctrump_varray *var_info_vec,
02294 struct ctrump_intmap *var_info_map,
02295 struct ctrump_mempool *tmp_alloc)
02296 {
02297 int i;
02298 for (i=0; i<num_bb; i++) {
02299 struct partial_bb *bb = bb_vec[i];
02300 int j;
02301 int n = bb->exprs.nelem;
02302 struct partial_bb_expr *exprs = bb->exprs.elements;
02303 for (j=0; j<n; j++) {
02304 switch (exprs[j].code) {
02305 case BB_EXPR:
02306 assign_var_info_expr(var_info_vec, var_info_map,
02307 exprs[j].u.expr, num_bb, tmp_alloc);
02308 break;
02309 }
02310 }
02311 }
02312
02313 return var_info_vec->nelem;
02314 }
02315
02319 static void
02320 calc_df(struct partial_bb **dfs_order,
02321 int num_bb,
02322 struct ctrump_intmap *varinfo_map,
02323 int num_var_info,
02324 ctrump_bitmap_t tmp_bitmap)
02325 {
02326 int i,j;
02327 int changed = 1;
02328
02329 for (i=0; i<num_bb; i++) {
02330 struct partial_bb *bb = dfs_order[i];
02331 ctrump_bitmap_copy(bb->live, bb->use, num_var_info);
02332 }
02333
02334 while (changed) {
02335 changed = 0;
02336
02337 for (i=0; i<num_bb; i++) {
02338 struct partial_bb *bb = dfs_order[i];
02339 int np = bb->succs.nelem;
02340 struct partial_bb **pb = bb->succs.elements;
02341 ctrump_bitmap_t live = bb->live;
02342
02343 ctrump_bitmap_copy(tmp_bitmap, bb->live, num_var_info);
02344
02345 for (j=0; j<np; j++) {
02346
02347 ctrump_bitmap_nand_or(live, pb[j]->live, pb[j]->kill, live, num_var_info);
02348 ctrump_bitmap_or(live, live, pb[j]->use, num_var_info);
02349 }
02350
02351 if (ctrump_bitmap_eq(live, tmp_bitmap, num_var_info) == 0) {
02352 changed = 1;
02353 }
02354 }
02355 }
02356 }
02357
02361 static void
02362 resolve_bb_vec(struct ctrump_bb **bb_vec,
02363 struct ctrump_varray *partial_vec,
02364 struct ctrump_bb **basic_blocks)
02365 {
02366 int n = partial_vec->nelem, i;
02367 struct partial_bb *target;
02368
02369 for (i=0; i<n; i++) {
02370 target = VA_ELEM(struct partial_bb*, partial_vec, i);
02371 bb_vec[i] = basic_blocks[target->id];
02372 }
02373 }
02374
02378 static int
02379 build_cfg(struct ctrump_cfg *ret,
02380 struct ctrump_intmap *var_info_map,
02381 struct ctrump_mempool *cfg_pool,
02382 struct ctrump_mempool *varmap_pool,
02383 const struct ctrump_compound_stmt *stmts,
02384 struct build_cfg_env *env)
02385 {
02386 struct partial_bb *start, *end, *bb;
02387 struct flow_env flow;
02388 int i, num_bb, num_create_bb, r, num_var_info;
02389 struct ctrump_bb **basic_blocks;
02390 ctrump_bitmap_t bb_bitmap;
02391 struct ctrump_varray var_set;
02392 ctrump_bitmap_t tmp_bmp;
02393 struct ctrump_cfg_var_info *vi;
02394 struct partial_var_info *pvi;
02395 struct ctrump_intmap tmp_var_map;
02396 struct ctrump_intmap_iterator iter;
02397 struct ctrump_intmap_bucket *b;
02398 struct ctrump_varray pdg_node_list;
02399
02400 start = new_bb(env, NULL);
02401 end = new_bb(env, NULL);
02402
02403 flow.return_to = end;
02404 flow.break_to = NULL;
02405 flow.continue_to = NULL;
02406 flow.loop_cfg = NULL;
02407
02408 bb = start;
02409 r = build_cfg_compound(stmts, env, &flow, &bb, NULL);
02410 if (r < 0)
02411 return r;
02412
02413
02414 if (bb != end) {
02415 append_succs_maybe(bb, end, env);
02416 }
02417
02418 num_create_bb = env->bb_id;
02419
02420 bb_bitmap = zero_bmp(num_create_bb, &env->tmp_alloc);
02421
02422
02423 num_bb = dfs_order(start, env, num_create_bb, bb_bitmap);
02424
02425
02426 build_dom(env, num_bb);
02427
02428
02429 find_df(env, num_bb);
02430
02431 basic_blocks = ctrump_mempool_alloc(env->cfg_pool, sizeof(struct ctrump_bb*)*num_bb);
02432
02433 ctrump_varray_init_pool(&var_set, 16, sizeof(struct partial_var_info), &env->tmp_alloc);
02434
02435 ctrump_intmap_init_pool(&tmp_var_map, 45, &env->tmp_alloc);
02436 num_var_info = assign_var_info((struct partial_bb**)env->basic_blocks.elements,
02437 env->basic_blocks.nelem,
02438 &var_set,
02439 &tmp_var_map,
02440 &env->tmp_alloc);
02441 ctrump_intmap_resize_pool(var_info_map, &tmp_var_map, varmap_pool);
02442
02443 vi = ctrump_mempool_alloc(env->cfg_pool, sizeof(struct ctrump_cfg_var_info)*num_var_info);
02444 pvi = var_set.elements;
02445 for (i=0; i<num_var_info; i++) {
02446 vi[i] = pvi[i].result;
02447 }
02448 ret->var_info = vi;
02449 ret->num_var = num_var_info;
02450
02451
02452 ctrump_intmap_iterator_begin(&iter, var_info_map);
02453 while (ctrump_intmap_iterator_next(&b, &iter, var_info_map)) {
02454 int map_val = (intptr_t)b->val;
02455 b->val = &pvi[map_val];
02456 pvi[map_val].map_val = map_val;
02457 }
02458
02459 for (i=0; i<num_bb; i++) {
02460 struct partial_bb *pb = VA_ELEM(struct partial_bb*, &env->basic_blocks, i);
02461 pb->use = zero_bmp(num_var_info, env->cfg_pool);
02462 pb->kill = zero_bmp(num_var_info, env->cfg_pool);
02463 pb->live = zero_bmp(num_var_info, env->cfg_pool);
02464 pb->phi_inserted = zero_bmp(num_var_info, &env->tmp_alloc);
02465 }
02466
02467 for (i=0; i<num_bb; i++) {
02468 struct partial_bb *pb = VA_ELEM(struct partial_bb*, &env->basic_blocks, i);
02469 int r = extract_load_store(pb, var_info_map, env->error, cfg_pool, &env->tmp_alloc);
02470 if (r < 0) {
02471 return r;
02472 }
02473 }
02474
02475 tmp_bmp = zero_bmp(num_var_info, &env->tmp_alloc);
02476
02477
02478 calc_df(env->dfs_order, num_bb,
02479 var_info_map, num_var_info, tmp_bmp);
02480
02481
02482 env->next_id = insert_phi(env->dfs_order, num_bb,
02483 var_set.elements, num_var_info, env->next_id, tmp_bmp, env->cfg_pool);
02484
02485 ctrump_varray_init(&pdg_node_list, 16, sizeof(struct ctrump_pdg_node*));
02486 env->next_id = assign_pdg_node(&pdg_node_list, start, var_set.elements,
02487 num_var_info, env->next_id, env->cfg_pool);
02488 ctrump_varray_discard(&pdg_node_list);
02489
02490
02491 for (i=0; i<num_bb; i++) {
02492 struct partial_bb *pb = VA_ELEM(struct partial_bb*, &env->basic_blocks, i);
02493 struct ctrump_bb *b = ctrump_mempool_alloc(env->cfg_pool, sizeof(*b));
02494 struct ctrump_phi_node *phis;
02495
02496 int j, n;
02497
02498 #define ALLOC_BB_VEC(aname, numname, vaname) \
02499 b->aname = ctrump_mempool_alloc(env->cfg_pool, sizeof(struct ctrump_bb*)*pb->vaname.nelem); \
02500 b->numname = pb->vaname.nelem;
02501
02502 ALLOC_BB_VEC(succs, num_succs, succs);
02503 ALLOC_BB_VEC(preds, num_preds, preds);
02504 ALLOC_BB_VEC(dom_children, num_dom_children, children);
02505 ALLOC_BB_VEC(dfs, num_dfs, dfs);
02506
02507 #define COPY_VEC(aname, numname, vaname) \
02508 b->aname = ctrump_varray_copy(&pb->vaname, env->cfg_pool); \
02509 b->numname = pb->vaname.nelem;
02510
02511 COPY_VEC(load_store.refs, load_store.num_ref, refs);
02512 COPY_VEC(load_store.stores, load_store.num_store, stores);
02513 COPY_VEC(load_store.mem_loads, load_store.num_mem_load, arr_loads);
02514 COPY_VEC(load_store.mem_stores, load_store.num_mem_store, arr_stores);
02515 COPY_VEC(load_store.ordered_load_store, load_store.num_memop, ordered_mem_load_store);
02516
02517 b->exprs = ctrump_mempool_alloc(env->cfg_pool, sizeof(struct ctrump_expr*)*pb->exprs.nelem);
02518 b->num_exprs = pb->exprs.nelem;
02519
02520 for (j=0; j<pb->exprs.nelem; j++) {
02521 struct partial_bb_expr *pbe = &((struct partial_bb_expr*)pb->exprs.elements)[j];
02522 assert(pbe->code == BB_EXPR);
02523 b->exprs[j] = pbe->u.expr;
02524 }
02525
02526 phis = b->phi_nodes = pb->phi_nodes;
02527 n = b->num_phi = pb->num_phi;
02528
02529 for (j=0; j<n; j++) {
02530 phis[j].merge_at = b;
02531 }
02532
02533 b->id = env->next_id ++;
02534 b->id_in_cfg = i;
02535 b->kill = pb->kill;
02536 b->use = pb->use;
02537 b->live = pb->live;
02538 b->num_var = num_var_info;
02539 b->loop_belong_to = pb->loop_cfg;
02540 b->flags = pb->flags;
02541
02542 basic_blocks[i] = b;
02543 }
02544
02545 for (i=0; i<num_bb; i++) {
02546 struct ctrump_bb *b = basic_blocks[i];
02547 struct partial_bb *pb = VA_ELEM(struct partial_bb*, &env->basic_blocks, i);
02548 struct pending_chain *pend;
02549
02550 resolve_bb_vec(b->succs, &pb->succs, basic_blocks);
02551 resolve_bb_vec(b->preds, &pb->preds, basic_blocks);
02552 resolve_bb_vec(b->dfs, &pb->dfs, basic_blocks);
02553 resolve_bb_vec(b->dom_children, &pb->children, basic_blocks);
02554
02555
02556
02557 pb->bb = b;
02558
02559 pend = pb->resolve_pending;
02560 while (pend) {
02561 *pend->resolve_ptr = b;
02562 pend = pend->chain;
02563 }
02564 }
02565
02566 ret->head = basic_blocks[start->id];
02567 ret->tail = basic_blocks[end->id];
02568 ret->num_bb = num_bb;
02569 ret->basic_blocks = basic_blocks;
02570
02571 ret->addressed = zero_bmp(num_var_info, env->cfg_pool);
02572 for (i=0; i<num_var_info; i++) {
02573 if (vi[i].var->addressed) {
02574 ctrump_bitmap_set(ret->addressed, i);
02575 }
02576 }
02577
02578 ret->global = zero_bmp(num_var_info, env->cfg_pool);
02579 for (i=0; i<num_var_info; i++) {
02580 enum ctrump_stor_class cls = vi[i].var->stor_class;
02581 (void)cls;
02582 if (! (cls == CTRUMP_STOR_CLASS_AUTO ||
02583 cls == CTRUMP_STOR_CLASS_AUTO_UNSPECIFIED ||
02584 cls == CTRUMP_STOR_CLASS_ARGMENT) ) {
02585 ctrump_bitmap_set(ret->global, i);
02586 }
02587 }
02588
02589
02590 ctrump_intmap_iterator_begin(&iter, var_info_map);
02591 while (ctrump_intmap_iterator_next(&b, &iter, var_info_map)) {
02592 int map_val = ((struct partial_var_info*)b->val)->map_val;
02593 b->val = &vi[map_val];
02594 }
02595
02596 return num_bb ;
02597 }
02598
02614 static int
02615 build_cfg_loop(struct ctrump_stmt *body,
02616 struct ctrump_expr *exit_cond,
02617 struct partial_bb *cond_bb_enter,
02618 struct partial_bb *cond_bb_exit,
02619 struct partial_bb *return_bb,
02620 struct partial_bb *continue_bb_enter,
02621 struct partial_bb *continue_bb_exit,
02622 struct ctrump_stmt *next_stmt,
02623 struct ctrump_loop_cfg_info *loop,
02624 struct build_cfg_env *env,
02625 struct ctrump_loop_cfg_info *outer_loop,
02626 struct partial_bb **current_bb_ptr)
02627 {
02628 struct partial_bb *current_bb = *current_bb_ptr;
02629 struct partial_bb *loop_body_bb;
02630 struct partial_bb *break_bb;
02631 int r;
02632 struct flow_env flow;
02633
02634 loop->exit_cond = exit_cond;
02635 loop->id = env->next_id++;
02636
02637 break_bb = get_id_bb_maybe(env, next_stmt, outer_loop, return_bb);
02638
02639 flow.return_to = return_bb;
02640 flow.break_to = break_bb;
02641 flow.continue_to = continue_bb_enter;
02642 flow.loop_cfg = loop;
02643
02644 loop_body_bb = new_bb(env, loop);
02645 cond_bb_enter->flags |= CTRUMP_BB_LOOP_ENTRY;
02646 append_pending(env, cond_bb_enter, &loop->cond_bb);
02647 append_pending(env, break_bb, &loop->break_bb);
02648 append_pending(env, loop_body_bb, &loop->body_start_bb);
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659 append_succs_maybe(current_bb, cond_bb_enter, env);
02660
02661 if (current_bb) {
02662 append_pending(env, current_bb, &loop->loop_pred);
02663 } else {
02664 loop->loop_pred = NULL;
02665 }
02666
02667 append_succs(cond_bb_exit, loop_body_bb, env);
02668 append_succs(cond_bb_exit, break_bb, env);
02669
02670 r = build_cfg_stmt(body, NULL, env, &flow, &loop_body_bb);
02671 if (r < 0)
02672 return r;
02673
02674
02675 if (loop_body_bb) {
02676 append_succs(loop_body_bb, continue_bb_enter, env);
02677 }
02678
02679 *current_bb_ptr = break_bb;
02680
02681 return 0;
02682 }
02683
02687 static int
02688 build_cfg_for(struct ctrump_loop_cfg_info **loop_ret,
02689 struct ctrump_expr *cond,
02690 struct ctrump_expr *iter,
02691 struct ctrump_stmt *body,
02692 struct ctrump_stmt *next_stmt,
02693 struct build_cfg_env *env,
02694 const struct flow_env *flow_env,
02695 struct partial_bb **current_bb_ptr)
02696 {
02697 struct partial_bb *cond_bb_enter, *cond_bb_exit;
02698 struct partial_bb *continue_bb_enter, *continue_bb_exit;
02699
02700 struct ctrump_loop_cfg_info *loop = ctrump_mempool_alloc(env->cfg_pool,
02701 sizeof(*loop));
02702
02703 *loop_ret = loop;
02704
02705 cond_bb_exit = cond_bb_enter = new_bb(env, loop);
02706 continue_bb_exit = continue_bb_enter = new_bb(env, loop);
02707
02708 build_cfg_expr(cond, body, env, loop, &cond_bb_exit);
02709 build_cfg_expr(iter, body, env, loop, &continue_bb_exit);
02710 append_succs(continue_bb_exit, cond_bb_enter, env);
02711
02712 return build_cfg_loop(body, cond,
02713 cond_bb_enter,
02714 cond_bb_exit,
02715 flow_env->return_to,
02716 continue_bb_enter,
02717 continue_bb_exit,
02718 next_stmt, loop, env,
02719 flow_env->loop_cfg, current_bb_ptr);
02720 }
02721
02725 static int
02726 build_cfg_while(struct ctrump_loop_cfg_info **loop_ret,
02727 struct ctrump_expr *cond,
02728 struct ctrump_stmt *body,
02729 struct ctrump_stmt *next_stmt,
02730 struct build_cfg_env *env,
02731 const struct flow_env *flow_env,
02732 struct partial_bb **current_bb_ptr)
02733 {
02734 struct partial_bb *cond_bb_enter, *cond_bb_exit;
02735 struct partial_bb *continue_bb;
02736 struct ctrump_loop_cfg_info *loop = ctrump_mempool_alloc(env->cfg_pool,
02737 sizeof(*loop));
02738
02739 *loop_ret = loop;
02740
02741 cond_bb_enter = cond_bb_exit = new_bb(env, loop);
02742 continue_bb = cond_bb_enter;
02743
02744 build_cfg_expr(cond, body, env, loop, &cond_bb_exit);
02745
02746 return build_cfg_loop(body, cond,
02747 cond_bb_enter,
02748 cond_bb_exit,
02749 flow_env->return_to,
02750 continue_bb,
02751 continue_bb,
02752 next_stmt, loop, env,
02753 flow_env->loop_cfg, current_bb_ptr);
02754 }
02755
02759 static int
02760 build_cfg_do_while(struct ctrump_expr *cond,
02761 struct ctrump_stmt *body,
02762 struct ctrump_stmt *next_stmt,
02763 struct build_cfg_env *env,
02764 const struct flow_env *flow_env,
02765 struct partial_bb **current_bb_ptr)
02766 {
02767 struct partial_bb *continue_bb;
02768 struct partial_bb *next_bb;
02769 struct partial_bb *body_bb, *body_bb_enter;
02770 struct flow_env flow;
02771 int r;
02772
02773 body_bb = body_bb_enter = get_id_bb(env, body, flow_env->loop_cfg);
02774 next_bb = get_id_bb_maybe(env, next_stmt, flow_env->loop_cfg, flow_env->return_to);
02775
02776 continue_bb = body_bb;
02777 flow.return_to = flow_env->return_to;
02778 flow.break_to = next_bb;
02779 flow.continue_to = continue_bb;
02780
02781 append_succs_maybe(*current_bb_ptr, body_bb_enter, env);
02782
02783 r = build_cfg_stmt(body, next_stmt,
02784 env, &flow, &body_bb);
02785 if (r < 0)
02786 return r;
02787
02788 build_cfg_expr_maybe(cond, body, env, flow_env->loop_cfg, &body_bb);
02789 append_succs_maybe(body_bb, body_bb_enter, env);
02790 if (next_stmt) {
02791 append_succs_maybe(body_bb, next_bb, env);
02792 }
02793
02794 *current_bb_ptr = body_bb;
02795
02796 return 0;
02797 }
02798
02802 static void
02803 build_cfg_initializer_list(struct ctrump_initializer_list *list,
02804 struct ctrump_stmt *stmt,
02805 struct build_cfg_env *env,
02806 struct ctrump_loop_cfg_info *cur_loop,
02807 struct partial_bb **current_bb_ptr)
02808 {
02809 int i, j, n, m;
02810 n = list->num_elem;
02811
02812 for (i=0; i<n; i++) {
02813 struct ctrump_initializer_list_elem *e = &list->elems[i];
02814
02815 m = e->num_designator;
02816 for (j=0; j<m; j++) {
02817 struct ctrump_designator *d = &e->designators_list[j];
02818
02819 switch (d->code) {
02820 case CTRUMP_DESIGNATOR_INDEX:
02821 build_cfg_expr_maybe(d->u.index.index,
02822 stmt, env, cur_loop, current_bb_ptr);
02823 break;
02824
02825 case CTRUMP_DESIGNATOR_IDENT:
02826
02827 break;
02828 }
02829 }
02830
02831 build_cfg_initializer(&e->initializer, stmt, env, cur_loop, current_bb_ptr);
02832 }
02833 }
02834
02838 static void
02839 build_cfg_initializer(struct ctrump_initializer *init,
02840 struct ctrump_stmt *stmt,
02841 struct build_cfg_env *env,
02842 struct ctrump_loop_cfg_info *cur_loop,
02843 struct partial_bb **current_bb_ptr)
02844 {
02845 switch (init->code) {
02846 case CTRUMP_INITIALIZER_EMPTY:
02847 break;
02848
02849 case CTRUMP_INITIALIZER_EXPR:
02850 build_cfg_expr_maybe(init->u.expr, stmt, env, cur_loop, current_bb_ptr);
02851 break;
02852
02853 case CTRUMP_INITIALIZER_NESTED:
02854 build_cfg_initializer_list(init->u.nest, stmt, env, cur_loop, current_bb_ptr);
02855 break;
02856 }
02857 }
02858
02862 static void
02863 build_cfg_decl(struct ctrump_stmt *stmt,
02864 struct ctrump_decl *decl,
02865 struct build_cfg_env *env,
02866 struct ctrump_loop_cfg_info *cur_loop,
02867 struct partial_bb **current_bb_ptr)
02868 {
02869 int i, n = decl->num_decls;
02870 for (i=0; i<n; i++) {
02871 struct ctrump_decl_with_init *dwi = &decl->decls[i];
02872 build_cfg_initializer(&dwi->initializer, stmt, env, cur_loop, current_bb_ptr);
02873 }
02874 }
02875
02879 static int
02880 build_cfg_stmt(struct ctrump_stmt *stmt,
02881 struct ctrump_stmt *next_stmt,
02882 struct build_cfg_env *env,
02883 const struct flow_env *flow_env,
02884 struct partial_bb **current_bb_ptr
02885 )
02886 {
02887 struct partial_bb *next_bb;
02888 struct partial_bb *current_bb = *current_bb_ptr;
02889 struct partial_bb *then_bb, *else_bb;
02890 int r;
02891
02892 switch (stmt->code) {
02893 case CTRUMP_STMT_GOTO: {
02894 const struct ctrump_goto_stmt *s = &stmt->u.goto_;
02895 struct label_table *t, *table;
02896 struct partial_bb *label_bb;
02897 table = env->label_table;
02898 HASH_FIND_SYM(table, s->label, t);
02899
02900 label_bb = get_id_bb(env, t->stmt, flow_env->loop_cfg);
02901 append_succs_maybe(current_bb, label_bb, env);
02902
02903 current_bb = NULL;
02904 break;
02905 }
02906
02907 case CTRUMP_STMT_CONTINUE:
02908 if (flow_env->continue_to == NULL) {
02909 env->error->code = CTRUMP_BUILD_CFG_ERROR_CONTINUE_IN_NOT_LOOP;
02910 env->error->stmt = stmt;
02911 return -1;
02912 }
02913
02914 append_succs_maybe(current_bb, flow_env->continue_to, env);
02915 current_bb = NULL;
02916 break;
02917
02918 case CTRUMP_STMT_BREAK:
02919 if (flow_env->break_to == NULL) {
02920 env->error->code = CTRUMP_BUILD_CFG_ERROR_BREAK_IN_NOT_LOOP;
02921 env->error->stmt = stmt;
02922 return -1;
02923 }
02924 append_succs_maybe(current_bb, flow_env->break_to, env);
02925 current_bb = NULL;
02926 break;
02927
02928 case CTRUMP_STMT_RETURN_EXPR:
02929 build_cfg_expr_maybe(&stmt->u.ret_expr.retval, stmt, env, flow_env->loop_cfg, ¤t_bb);
02930
02931
02932 case CTRUMP_STMT_RETURN:
02933 append_succs_maybe(current_bb, flow_env->return_to, env);
02934 current_bb = NULL;
02935 break;
02936
02937 case CTRUMP_STMT_LABELED:
02938 if (BMP_P(env->label_ref_bmp, stmt->id)) {
02939 next_bb = get_id_bb(env, stmt->u.labeled.stmt, flow_env->loop_cfg);
02940 append_succs(current_bb, next_bb, env);
02941 current_bb = next_bb;
02942 }
02943
02944 build_cfg_stmt(stmt->u.labeled.stmt, next_stmt, env, flow_env, ¤t_bb);
02945 break;
02946
02947 case CTRUMP_STMT_COMPOUND:
02948 r = build_cfg_compound(&stmt->u.compound,
02949 env, flow_env, ¤t_bb, next_stmt);
02950 if (r < 0)
02951 return r;
02952 break;
02953
02954 case CTRUMP_STMT_IF:
02955 build_cfg_expr_maybe(&stmt->u.if_.cond, stmt, env, flow_env->loop_cfg, ¤t_bb);
02956
02957 if (current_bb) {
02958 then_bb = get_id_bb(env, stmt->u.if_.body, flow_env->loop_cfg);
02959 append_succs(current_bb, then_bb, env);
02960 } else {
02961 then_bb = NULL;
02962 }
02963 build_cfg_stmt(stmt->u.if_.body, NULL,
02964 env, flow_env, &then_bb);
02965
02966 if (current_bb) {
02967 next_bb = get_id_bb_maybe(env, next_stmt, flow_env->loop_cfg, flow_env->return_to);
02968 append_succs_maybe(then_bb, next_bb, env);
02969 append_succs(current_bb, next_bb, env);
02970 current_bb = next_bb;
02971 } else if (then_bb) {
02972 current_bb = then_bb;
02973 } else {
02974
02975 current_bb = NULL;
02976 }
02977 break;
02978
02979 case CTRUMP_STMT_IF_ELSE:
02980 build_cfg_expr_maybe(&stmt->u.if_else.cond, stmt, env, flow_env->loop_cfg, ¤t_bb);
02981
02982 if (current_bb) {
02983 then_bb = get_id_bb(env, stmt->u.if_else.then_body, flow_env->loop_cfg);
02984 else_bb = get_id_bb(env, stmt->u.if_else.else_body, flow_env->loop_cfg);
02985 append_succs(current_bb, then_bb, env);
02986 append_succs(current_bb, else_bb, env);
02987 } else {
02988 then_bb = NULL;
02989 else_bb = NULL;
02990 }
02991
02992 build_cfg_stmt(stmt->u.if_else.then_body, NULL,
02993 env, flow_env, &then_bb);
02994 build_cfg_stmt(stmt->u.if_else.else_body, NULL,
02995 env, flow_env, &else_bb);
02996
02997 if (then_bb && else_bb) {
02998 next_bb = get_id_bb_maybe(env, next_stmt, flow_env->loop_cfg, flow_env->return_to);
02999 append_succs(then_bb, next_bb, env);
03000 append_succs(else_bb, next_bb, env);
03001
03002 current_bb = next_bb;
03003 } else if (then_bb) {
03004 current_bb = then_bb;
03005 } else if (else_bb) {
03006 current_bb = else_bb;
03007 } else {
03008
03009 current_bb = NULL;
03010 }
03011 break;
03012
03013 case CTRUMP_STMT_EXPR:
03014 build_cfg_expr_maybe(&stmt->u.expr.expr, stmt, env, flow_env->loop_cfg, ¤t_bb);
03015 break;
03016
03017 case CTRUMP_STMT_FOR:
03018 build_cfg_expr_maybe(&stmt->u.for_.init, stmt, env, flow_env->loop_cfg, ¤t_bb);
03019 r = build_cfg_for(&stmt->u.for_.loop_cfg,
03020 &stmt->u.for_.cond,
03021 &stmt->u.for_.iter,
03022 stmt->u.for_.body,
03023 next_stmt, env, flow_env, ¤t_bb);
03024 stmt->u.for_.loop_cfg->loop_stmt = stmt;
03025 if (r < 0)
03026 return r;
03027 break;
03028
03029 case CTRUMP_STMT_WHILE:
03030 r = build_cfg_while(&stmt->u.while_.loop_cfg,
03031 &stmt->u.while_.cond,
03032 stmt->u.while_.body,
03033 next_stmt, env, flow_env, ¤t_bb);
03034 stmt->u.while_.loop_cfg->loop_stmt = stmt;
03035 if (r < 0)
03036 return r;
03037 break;
03038
03039 case CTRUMP_STMT_DO_WHILE:
03040 r = build_cfg_do_while(&stmt->u.do_while.cond,
03041 stmt->u.do_while.body,
03042 next_stmt, env, flow_env, ¤t_bb);
03043 if (r < 0)
03044 return r;
03045 break;
03046
03047 case CTRUMP_STMT_DECL:
03048 build_cfg_decl(stmt, &stmt->u.decl, env, flow_env->loop_cfg, ¤t_bb);
03049 break;
03050
03051 case CTRUMP_STMT_FOR_DECL:
03052 build_cfg_decl(stmt, &stmt->u.for_decl.init, env, flow_env->loop_cfg, ¤t_bb);
03053 r = build_cfg_for(&stmt->u.for_decl.loop_cfg,
03054 &stmt->u.for_decl.cond,
03055 &stmt->u.for_decl.iter,
03056 stmt->u.for_decl.body,
03057 next_stmt, env, flow_env, ¤t_bb);
03058 stmt->u.for_decl.loop_cfg->loop_stmt = stmt;
03059 if (r < 0)
03060 return r;
03061 break;
03062
03063 case CTRUMP_STMT_CASE:
03064 case CTRUMP_STMT_DEFAULT:
03065 case CTRUMP_STMT_SWITCH:
03066 ctrump_fixme("control flow");
03067 break;
03068
03069 case CTRUMP_STMT_PRAGMA:
03070 case CTRUMP_STMT_SLASLA_COMMENT:
03071 case CTRUMP_STMT_SLAAST_COMMENT:
03072 case CTRUMP_STMT_IFDEF:
03073 case CTRUMP_STMT_ASM:
03074 case CTRUMP_STMT_DEFINE:
03075 case CTRUMP_STMT_UNDEF:
03076 case CTRUMP_STMT_EMPTY:
03077 case CTRUMP_STMT_NEWLINE:
03078
03079 break;
03080
03081 case CTRUMP_STMT_LIST:
03082 ctrump_unreachable("stmt list");
03083 break;
03084 }
03085
03086 *current_bb_ptr = current_bb;
03087 return 0;
03088 }
03089
03090 int
03091 ctrump_build_cfg(struct ctrump_cfg *ret,
03092 struct ctrump_intmap *var_info_map,
03093 struct ctrump_build_cfg_error *error,
03094 const struct ctrump_fundef *def,
03095 struct ctrump_mempool *cfg_pool,
03096 struct ctrump_mempool *varmap_pool,
03097 int num_ast,
03098 int id_begin)
03099 {
03100 struct build_cfg_env env;
03101 int r, i, num_bb;
03102
03103 ctrump_mempool_init(&env.tmp_alloc, 1024);
03104
03105 env.label_ref_bmp = zero_bmp(num_ast, &env.tmp_alloc);
03106 env.stmt_bb_table = ctrump_mempool_alloc(&env.tmp_alloc, num_ast * sizeof(struct ctrump_bb*));
03107 env.next_id = id_begin;
03108 env.bb_id = 0;
03109 env.error = error;
03110 env.cfg_pool = cfg_pool;
03111
03112 ctrump_varray_init_pool(&env.basic_blocks, 16, sizeof(struct partial_bb*), &env.tmp_alloc);
03113
03114 for (i=0; i<num_ast; i++) {
03115 env.stmt_bb_table[i] = NULL;
03116 }
03117
03118 r = check_label_use(&env, &def->body);
03119 if (r < 0)
03120 goto quit;
03121
03122 num_bb = build_cfg(ret, var_info_map, cfg_pool, varmap_pool, &def->body, &env);
03123 delete_table(env.label_table);
03124 if (num_bb < 0) {
03125 r = -1;
03126 goto quit;
03127 }
03128
03129 r = env.next_id;
03130
03131 quit:
03132 ctrump_mempool_destroy(&env.tmp_alloc);
03133
03134 return r;
03135 }