/* Return VAR if there is already related to 's', otherwise create a new VAR. 'var_name': name of the variable, it is optional. 's': string's content. */ VAR * VAR_MGR::register_str(CHAR const* var_name, SYM * s, UINT align) { IS_TRUE0(s != NULL); VAR * v; if ((v = m_str_tab.get(s)) != NULL) { return v; } v = new_var(); CHAR buf[64]; if (var_name == NULL) { sprintf(buf, ".rodata_%zu", m_str_count++); VAR_name(v) = m_ru_mgr->add_to_symtab(buf); } else { VAR_name(v) = m_ru_mgr->add_to_symtab(var_name); } VAR_str(v) = s; VAR_data_type(v) = D_STR; VAR_elem_type(v) = D_UNDEF; IS_TRUE0(sizeof(CHAR) == 1); VAR_data_size(v) = xstrlen(SYM_name(s)) + 1; VAR_align(v) = align; VAR_is_global(v) = 1; //store in .data or .rodata assign_var_id(v); m_str_tab.set(s, v); return v; }
CHAR const* get_class_name(DexFile * df, DexClassDef const* class_info) { IS_TRUE0(class_info); CHAR const* class_name = dexStringByTypeIdx(df, class_info->classIdx); IS_TRUE0(class_name); return class_name; }
ABS_NODE * CFS_MGR::construct_abs_loop( IN IR_BB * entry, IN ABS_NODE * parent, IN BITSET * cur_region, IN GRAPH & cur_graph, IN OUT BITSET & visited) { IS_TRUE0(cur_region == NULL || cur_region->is_contain(IR_BB_id(entry))); IR_CFG * cfg = m_ru->get_cfg(); LI<IR_BB> * li = cfg->map_bb2li(entry); IS_TRUE0(li != NULL && LI_loop_head(li) == entry); ABS_NODE * node = new_abs_node(ABS_LOOP); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_loop_head(node) = entry; IR_BB * body_start; cfg->get_loop_two_kids(entry, NULL, &body_start); IS_TRUE0(body_start != NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); IS_TRUE0(ci != NULL && CFS_INFO_head(ci) == entry); IS_TRUE0(CFS_INFO_loop_body(ci)->is_contain(*LI_bb_set(li))); BITSET loc_visited; ABS_NODE_loop_body(node) = construct_abs_tree(body_start, node, LI_bb_set(li), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(IR_BB_id(entry)); return node; }
EDGE * GRAPH::new_edge(VERTEX * from, VERTEX * to) { IS_TRUE(m_pool != NULL, ("not yet initialized.")); if (from == NULL || to == NULL) return NULL; EDGE teste; VERTEX testfrom, testto; if (m_is_unique) { VERTEX_id(&testfrom) = VERTEX_id(from); VERTEX_id(&testto) = VERTEX_id(to); EDGE_from(&teste) = &testfrom; EDGE_to(&teste) = &testto; if (m_is_direction) { return m_edges.append((ULONG)&teste, NULL); } else { EDGE * e = NULL; if (m_edges.find(&teste, &e)) { IS_TRUE0(e); return e; } //Both check from->to and to->from EDGE_from(&teste) = &testto; EDGE_to(&teste) = &testfrom; return m_edges.append((ULONG)&teste, NULL); } IS_TRUE0(0); } return m_edges.append(new_edge_c(from, to)); }
//All global prs must be mapped. bool DEX_REGION::verify_ra_res(RA & ra, PRNO2UINT & prno2v) { GLTM * gltm = ra.get_gltm(); SVECTOR<GLT*> * gltv = gltm->get_gltvec(); for (UINT i = 0; i < gltm->get_num_of_glt(); i++) { GLT * g = gltv->get(i); if (g == NULL) { continue; } IS_TRUE0(g->has_allocated()); if (GLT_bbs(g) == NULL) { //parameter may be have no occ. continue; } bool find; prno2v.get(GLT_prno(g), &find); IS_TRUE0(find); } IR_BB_LIST * bbl = get_bb_list(); for (IR_BB * bb = bbl->get_head(); bb != NULL; bb = bbl->get_next()) { LTM * ltm = gltm->map_bb2ltm(bb); if (ltm == NULL) { continue; } SVECTOR<LT*> * lvec = ltm->get_lt_vec(); for (INT i = 0; i <= lvec->get_last_idx(); i++) { LT * l = lvec->get(i); if (l == NULL) { continue; } IS_TRUE0(l->has_allocated()); bool find; prno2v.get(LT_prno(l), &find); IS_TRUE0(find); } } return true; }
void DEX_REGION::update_ra_res(IN RA & ra, OUT PRNO2UINT & prno2v) { prno2v.maxreg = ra.get_maxreg(); prno2v.paramnum = ra.get_paramnum(); GLTM * gltm = ra.get_gltm(); IR_BB_LIST * bbl = get_bb_list(); prno2v.clean(); for (IR_BB * bb = bbl->get_head(); bb != NULL; bb = bbl->get_next()) { LTM * ltm = gltm->map_bb2ltm(bb); if (ltm == NULL) { continue; } SVECTOR<LT*> * lvec = ltm->get_lt_vec(); for (INT i = 0; i <= lvec->get_last_idx(); i++) { LT * l = lvec->get(i); if (l == NULL) { continue; } IS_TRUE0(l->has_allocated()); bool find; UINT v = prno2v.get(LT_prno(l), &find); if (find) { //each prno is corresponding to a unqiue vreg. IS_TRUE0(v == LT_phy(l)); } else { prno2v.set(LT_prno(l), LT_phy(l)); } } } prno2v.dump(); IS_TRUE0(verify_ra_res(ra, prno2v)); }
VN * IR_GVN::comp_sc_by_anon_domdef(IR const* exp, IR const* domdef, bool & change) { IS_TRUE0((IR_type(exp) == IR_LD || IR_type(exp) == IR_PR) && m_du->is_may_def(domdef, exp, false)); SCVNE2VN * vnexp_map = m_def2sctab.get(domdef); UINT dtsz = exp->get_dt_size(m_dm); MD const* md = exp->get_exact_ref(); IS_TRUE0(md); VNE_SC vexp(MD_id(md), exp->get_ofst(), dtsz); /* NOTE: foo(); v1; //s1 goo(); v1; //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new SCVNE2VN(m_pool, 16); //bsize to be evaluate. m_def2sctab.set(domdef, vnexp_map); } VN * vn = vnexp_map->get(&vexp); if (vn == NULL) { vn = new_vn(); VN_type(vn) = VN_VAR; vnexp_map->setv((OBJTY)&vexp, vn); } m_ir2vn.set(IR_id(exp), vn); change = true; return vn; }
//GVN try to assign a value numbers to expressions. bool IR_GVN::perform(OPT_CTX & oc) { IR_BB_LIST * bbl = m_ru->get_bb_list(); if (bbl->get_elem_count() == 0) { return false; } START_TIMER_AFTER(); m_ru->check_valid_and_recompute(&oc, OPT_DU_CHAIN, OPT_DU_REF, OPT_RPO, OPT_DOM, OPT_UNDEF); LIST<IR_BB*> * tbbl = m_cfg->get_bblist_in_rpo(); IS_TRUE0(tbbl->get_elem_count() == bbl->get_elem_count()); UINT count = 0; bool change = true; #ifdef DEBUG_GVN while (change && count < 10) { change = false; #endif for (IR_BB * bb = tbbl->get_head(); bb != NULL; bb = tbbl->get_next()) { process_bb(bb, change); } //end for BB count++; #ifdef DEBUG_GVN } //end while IS_TRUE0(!change && count <= 2); #endif //dump(); END_TIMER_AFTER(get_opt_name()); IS_TRUE0(verify()); m_is_valid = true; return true; }
//Return true if gvn is able to determine the result of 'ir'. bool IR_GVN::calc_cond_must_val(IN IR const* ir, bool & must_true, bool & must_false) { must_true = false; must_false = false; IS_TRUE0(ir->is_judge()); VN const* v1 = m_ir2vn.get(IR_id(BIN_opnd0(ir))); VN const* v2 = m_ir2vn.get(IR_id(BIN_opnd1(ir))); if (v1 == NULL || v2 == NULL) return false; switch (IR_type(ir)) { case IR_LT: case IR_GT: if (v1 == v2) { must_true = false; must_false = true; return true; } break; case IR_LE: case IR_GE: if (v1 == v2) { must_true = true; must_false = false; return true; } break; case IR_NE: if (v1 == v2) { must_true = false; must_false = true; return true; } if (v1 != v2) { must_true = true; must_false = false; return true; } IS_TRUE0(0); break; case IR_EQ: if (v1 == v2) { must_true = true; must_false = false; return true; } if (v1 != v2) { must_true = false; must_false = true; return true; } IS_TRUE0(0); break; case IR_LAND: case IR_LOR: case IR_LNOT: break; default: IS_TRUE0(0); } return false; }
void DEX_PASS_MGR::perform_scalar_opt(OPT_CTX & oc) { LIST<IR_OPT*> opt_list; //A list of optimization. IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)register_opt(OPT_SSA_MGR); bool is_ssa_avail = false; if (ssamgr != NULL) { is_ssa_avail = ssamgr->is_ssa_construct(); } opt_list.append_tail(register_opt(OPT_CP)); opt_list.append_tail(register_opt(OPT_DCE)); opt_list.append_tail(register_opt(OPT_RP)); opt_list.append_tail(register_opt(OPT_CP)); opt_list.append_tail(register_opt(OPT_DCE)); opt_list.append_tail(register_opt(OPT_RP)); opt_list.append_tail(register_opt(OPT_CP)); opt_list.append_tail(register_opt(OPT_DCE)); opt_list.append_tail(register_opt(OPT_LOOP_CVT)); opt_list.append_tail(register_opt(OPT_LICM)); opt_list.append_tail(register_opt(OPT_GCSE)); ((IR_DCE*)register_opt(OPT_DCE))->set_elim_cfs(false); ((IR_DCE*)register_opt(OPT_DCE))->set_ssa_available(is_ssa_avail); if (opt_list.get_elem_count() != 0) { LOG("\tScalar optimizations for '%s'", m_ru->get_ru_name()); } bool change; UINT count = 0; //do { change = false; for (IR_OPT * opt = opt_list.get_head(); opt != NULL; opt = opt_list.get_next()) { CHAR const* optn = opt->get_opt_name(); LOG("\t\tpass %s", optn); IS_TRUE0(verify_ir_and_bb(m_ru->get_bb_list(), m_dm)); ULONGLONG t = getusec(); //dump_bbs(m_ru->get_bb_list(), "before"); //m_ru->get_cfg()->dump_vcg("before.vcg"); bool doit = opt->perform(oc); //dump_bbs(m_ru->get_bb_list(), "after"); //m_ru->get_cfg()->dump_vcg("after.vcg"); append_ti(opt->get_opt_name(), getusec() - t); if (doit) { LOG("\t\t\tchanged"); change = true; IS_TRUE0(verify_ir_and_bb(m_ru->get_bb_list(), m_dm)); IS_TRUE0(m_ru->get_cfg()->verify()); } } count++; //} while (change && count < 20); //IS_TRUE0(!change); }
CHAR const* AOC_DX_MGR::get_method_name(UINT method_idx) { DexMethodId const* method_id = dexGetMethodId(m_df, method_idx); IS_TRUE0(method_id); CHAR const* method_name = dexStringById(m_df, method_id->nameIdx); IS_TRUE0(method_name); return method_name; }
void DEX_REGION::process_simply(OUT PRNO2UINT & prno2v, UINT param_num, UINT vregnum, DEX2IR & d2ir, UINT2PR * v2pr, IN PRNO2UINT * pr2v, TYIDR * tr) { LOG("\t\t Invoke DEX_REGION::process_simply '%s'", get_ru_name()); if (get_ir_list() == NULL) { return ; } OPT_CTX oc; OPTC_show_comp_time(oc) = g_show_comp_time; CHAR const* ru_name = get_ru_name(); construct_ir_bb_list(); IS_TRUE0(verify_ir_and_bb(get_bb_list(), get_dm())); RU_ana(this)->m_ir_list = NULL; //All IRs have been moved to each IR_BB. IR_CFG * cfg = init_cfg(oc); cfg->loop_analysis(oc); PASS_MGR * pm = new_pass_mgr(); OPTC_pass_mgr(oc) = pm; //record pass manager. if (g_do_ssa && OPTC_pass_mgr(oc) != NULL) { //Convert program to ssa form. IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)OPTC_pass_mgr(oc)-> register_opt(OPT_SSA_MGR); IS_TRUE0(ssamgr); ssamgr->construction(oc, this); } init_aa(oc); init_du(oc); IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)pm->query_opt(OPT_SSA_MGR); if (ssamgr != NULL && ssamgr->is_ssa_construct()) { //Destruct ssa form. ssamgr->destruction_in_bblist_order(); } delete pm; OPTC_pass_mgr(oc) = NULL; #if 1 //Do not allocate register. prno2v.clean(); prno2v.copy(*d2ir.get_pr2v_map()); return; #else //Allocate register. RA ra(this, tr, param_num, vregnum, v2pr, pr2v, &m_var2pr); LOG("\t\tdo DEX Register Allcation for '%s'", ru_name); ra.perform(oc); update_ra_res(ra, prno2v); #endif }
//'var_name': name of the variable, it is optional. VAR * VAR_MGR::register_var(SYM * var_name, UINT tyid, UINT align, UINT flag) { IS_TRUE0(var_name != NULL && tyid != 0); DTD const* d = m_dm->get_dtd(tyid); IS_TRUE0(d); return register_var(var_name, DTD_rty(d), DTD_vec_ety(d), DTD_ptr_base_sz(d), m_dm->get_dtd_bytesize(d), align, flag); }
/* NOTE: IPA should only be performed in top level region, since it might incur the memory blow up. */ bool IPA::perform(OPT_CTX & oc) { IS_TRUE0(OPTC_is_callg_valid(oc)); REGION * top = m_ru_mgr->get_top_region(); if (top == NULL) return false; IS_TRUE0(RU_type(top) == RU_PROGRAM); //start do cp_prop //... // return true; }
//Return true if b is control dependent on a. bool CDG::is_cd(UINT a, UINT b) { IS_TRUE0(get_vertex(b)); VERTEX * v = get_vertex(a); IS_TRUE0(v != NULL); EDGE_C * out = VERTEX_out_list(v); while (out != NULL) { if (VERTEX_id(EDGE_to(EC_edge(out))) == b) { return true; } out = EC_next(out); } return false; }
void DEX_REGION::process(OUT PRNO2UINT & prno2v, UINT param_num, UINT vregnum, UINT2PR * v2pr, IN PRNO2UINT * pr2v, TYIDR * tr) { if (get_ir_list() == NULL) { return; } OPT_CTX oc; OPTC_show_comp_time(oc) = g_show_comp_time; g_indent = 0; note("\n==---- REGION_NAME:%s ----==", get_ru_name()); prescan(get_ir_list()); RU_is_pr_unique_for_same_no(this) = true; //g_do_ssa = true; PASS_MGR * pm = new_pass_mgr(); OPTC_pass_mgr(oc) = pm; high_process(oc); middle_process(oc); IR_SSA_MGR * ssamgr = (IR_SSA_MGR*)pm->query_opt(OPT_SSA_MGR); if (ssamgr != NULL && ssamgr->is_ssa_construct()) { ssamgr->destruction_in_bblist_order(); } delete pm; OPTC_pass_mgr(oc) = NULL; if (RU_type(this) != RU_FUNC) { return; } IR_BB_LIST * bbl = get_bb_list(); if (bbl->get_elem_count() == 0) { return; } IS_TRUE0(verify_ir_and_bb(bbl, get_dm())); RF_CTX rf; RC_insert_cvt(rf) = false; //Do not insert cvt for DEX code. refine_ir_bb_list(bbl, rf); IS_TRUE0(verify_ir_and_bb(bbl, get_dm())); RA ra(this, tr, param_num, vregnum, v2pr, pr2v, &m_var2pr); LOG("\t\tdo DEX Register Allcation for '%s'", get_ru_name()); ra.perform(oc); update_ra_res(ra, prno2v); }
VN * IR_GVN::register_bin_vn(IR_TYPE irt, VN const* v0, VN const* v1) { IS_TRUE0(v0 && v1); if (is_commutative(irt) && (VN_id(v0) > VN_id(v1))) { return register_bin_vn(irt, v1, v0); } else if (irt == IR_GT) { return register_bin_vn(IR_LT, v1, v0); } else if (irt == IR_GE) { return register_bin_vn(IR_LE, v1, v0); } VEC2 * v0_vec = m_irt_vec.get(irt); if (v0_vec == NULL) { v0_vec = new VEC2(); m_vec_lst.append_tail((SVECTOR<VN*>*)v0_vec); m_irt_vec.set(irt, v0_vec); } VEC1 * v1_vec = v0_vec->get(VN_id(v0)); if (v1_vec == NULL) { v1_vec = new VEC1(); m_vec_lst.append_tail((SVECTOR<VN*>*)v1_vec); m_vnvec_lst.append_tail(v1_vec); v0_vec->set(VN_id(v0), v1_vec); } VN * res = v1_vec->get(VN_id(v1)); if (res == NULL) { res = new_vn(); VN_type(res) = VN_OP; VN_op(res) = irt; v1_vec->set(VN_id(v1), res); } return res; }
LABEL_INFO * new_label(SMEM_POOL * pool) { LABEL_INFO * p = (LABEL_INFO*)smpool_malloc_h(sizeof(LABEL_INFO), pool); IS_TRUE0(p); memset(p, 0, sizeof(LABEL_INFO)); return p; }
//Compute VN for array according to anonymous domdef. VN * IR_GVN::comp_array_by_anon_domdef(IR const* arr, VN const* basevn, VN const* ofstvn, IR const* domdef, bool & change) { IS_TRUE0(IR_type(arr) == IR_ARRAY && m_du->is_may_def(domdef, arr, false)); ARR_VNE2VN * vnexp_map = m_def2arrtab.get(domdef); UINT dtsz = arr->get_dt_size(m_dm); VNE_ARR vexp(VN_id(basevn), VN_id(ofstvn), ARR_ofst(arr), dtsz); /* NOTE: foo(); array(v1); //s1 goo(); array(v1); //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new ARR_VNE2VN(m_pool, 16); //bsize to be evaluate. m_def2arrtab.set(domdef, vnexp_map); } VN * vn = vnexp_map->get(&vexp); if (vn == NULL) { vn = new_vn(); VN_type(vn) = VN_OP; VN_op(vn) = IR_ARRAY; vnexp_map->setv((OBJTY)&vexp, vn); } m_ir2vn.set(IR_id(arr), vn); change = true; return vn; }
//Attemp to compute POINT-TO set via the IR type. virtual MD * comp_point_to_via_type(IR const* ir) { IR_AI * ai = IR_ai(ir); IS_TRUE0(ir && ai); TBAA_AI * ty = (TBAA_AI*)ai->get(IRAI_TBAA); if (ty == NULL) { return NULL; } MD * md = m_tyid2md.get(ty->tyid); if (md != NULL) { return md; } CHAR buf[64]; sprintf(buf, "dummy%d", ty->tyid); VAR * dummy = m_var_mgr->register_var(buf, D_MC, D_UNDEF, 0, 1, 1, VAR_GLOBAL); VAR_is_addr_taken(dummy) = true; VAR_allocable(dummy) = false; m_ru->add_to_var_tab(dummy); MD dummy_md; MD_base(&dummy_md) = dummy; MD_size(&dummy_md) = 0; MD_ty(&dummy_md) = MD_UNBOUND; MD_is_addr_taken(&dummy_md) = true; MD * entry = m_md_sys->register_md(dummy_md); m_tyid2md.set(ty->tyid, entry); return entry; }
void dump_lab(LABEL_INFO const* li) { if (g_tfile == NULL) return; if (LABEL_INFO_type(li) == L_ILABEL) { fprintf(g_tfile, "\nilabel(" ILABEL_STR_FORMAT ")", ILABEL_CONT(li)); } else if (LABEL_INFO_type(li) == L_CLABEL) { fprintf(g_tfile, "\nclabel(" CLABEL_STR_FORMAT ")", CLABEL_CONT(li)); } else if (LABEL_INFO_type(li) == L_PRAGMA) { fprintf(g_tfile, "\npragms(%s)", SYM_name(LABEL_INFO_pragma(li))); } else { IS_TRUE0(0); } if (LABEL_INFO_b1(li) != 0) { fprintf(g_tfile, "("); } if (LABEL_INFO_is_try_start(li)) { fprintf(g_tfile, "try_start "); } if (LABEL_INFO_is_try_end(li)) { fprintf(g_tfile, "try_end "); } if (LABEL_INFO_is_catch_start(li)) { fprintf(g_tfile, "catch_start "); } if (LABEL_INFO_is_used(li)) { fprintf(g_tfile, "used "); } if (LABEL_INFO_b1(li) != 0) { fprintf(g_tfile, ")"); } fflush(g_tfile); }
CHAR const* AOC_DX_MGR::get_class_name_by_declaration_id(UINT cls_def_idx) { DexClassDef const* class_info = dexGetClassDef(m_df, cls_def_idx); CHAR const* class_name = dexStringByTypeIdx(m_df, class_info->classIdx); IS_TRUE0(class_name); return class_name; }
void DGRAPH::sort_dom_tree_in_preorder(IN GRAPH & dom_tree, IN VERTEX * root, OUT LIST<VERTEX*> & lst) { IS_TRUE0(root); BITSET is_visited; is_visited.bunion(VERTEX_id(root)); lst.append_tail(root); VERTEX * v; SSTACK<VERTEX*> stk; stk.push(root); while ((v = stk.pop()) != NULL) { if (!is_visited.is_contain(VERTEX_id(v))) { is_visited.bunion(VERTEX_id(v)); stk.push(v); //The only place to process vertex. lst.append_tail(v); } //Visit children. EDGE_C * el = VERTEX_out_list(v); VERTEX * succ; while (el != NULL) { succ = EDGE_to(EC_edge(el)); if (!is_visited.is_contain(VERTEX_id(succ))) { stk.push(v); stk.push(succ); break; } el = EC_next(el); } } }
CHAR const* AOC_DX_MGR::get_class_name_by_method_id(UINT method_idx) { DexMethodId const* method_id = dexGetMethodId(m_df, method_idx); IS_TRUE0(method_id); CHAR const* class_name = dexStringByTypeIdx(m_df, method_id->classIdx); return class_name; }
//'cur_region' covered 'entry'. ABS_NODE * CFS_MGR::construct_abs_if( IN IR_BB * entry, IN ABS_NODE * parent, IN GRAPH & cur_graph, IN OUT BITSET & visited) { ABS_NODE * node = new_abs_node(ABS_IF); set_map_bb2abs(entry, node); ABS_NODE_parent(node) = parent; ABS_NODE_if_head(node) = entry; IR_BB * true_body, * false_body; IR_CFG * cfg = m_ru->get_cfg(); cfg->get_if_three_kids(entry, &true_body, &false_body, NULL); CFS_INFO * ci = map_ir2cfsinfo(cfg->get_last_xr(entry)); IS_TRUE0(ci != NULL && CFS_INFO_head(ci) == entry); BITSET loc_visited; ABS_NODE_true_body(node) = construct_abs_tree(true_body, node, CFS_INFO_true_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); loc_visited.clean(); ABS_NODE_false_body(node) = construct_abs_tree(false_body, node, CFS_INFO_false_body(ci), cur_graph, loc_visited); visited.bunion(loc_visited); visited.bunion(IR_BB_id(entry)); return node; }
void DGRAPH::sort_dom_tree_in_postorder(IN GRAPH & dom_tree, IN VERTEX * root, OUT LIST<VERTEX*> & lst) { IS_TRUE0(root); BITSET is_visited; //Find the leaf node. VERTEX * v; SSTACK<VERTEX*> stk; stk.push(root); while ((v = stk.pop()) != NULL) { //Visit children first. EDGE_C * el = VERTEX_out_list(v); bool find = false; //find unvisited kid. VERTEX * succ; while (el != NULL) { succ = EDGE_to(EC_edge(el)); if (!is_visited.is_contain(VERTEX_id(succ))) { stk.push(v); stk.push(succ); find = true; break; } el = EC_next(el); } if (!find) { is_visited.bunion(VERTEX_id(v)); //The only place to process vertex. lst.append_tail(v); } } }
static void * xmalloc(ULONG size) { void * p = smpool_malloc_h(size, g_pool_general_used); IS_TRUE0(p); memset(p, 0, size); return p; }
//Compute VN for ild according to anonymous domdef. VN * IR_GVN::comp_ild_by_anon_domdef(IR const* ild, VN const* mlvn, IR const* domdef, bool & change) { IS_TRUE0(IR_type(ild) == IR_ILD && m_du->is_may_def(domdef, ild, false)); ILD_VNE2VN * vnexp_map = m_def2ildtab.get(domdef); UINT dtsz = ild->get_dt_size(m_dm); VNE_ILD vexp(VN_id(mlvn), ILD_ofst(ild), dtsz); /* NOTE: foo(); ild(v1); //s1 goo(); ild(v1); //s2 vn of s1 should not same with s2. */ if (vnexp_map == NULL) { vnexp_map = new ILD_VNE2VN(m_pool, 16); //bsize to be evaluate. m_def2ildtab.set(domdef, vnexp_map); } VN * ildvn = vnexp_map->get(&vexp); if (ildvn == NULL) { ildvn = new_vn(); VN_type(ildvn) = VN_OP; VN_op(ildvn) = IR_ILD; vnexp_map->setv((OBJTY)&vexp, ildvn); } m_ir2vn.set(IR_id(ild), ildvn); change = true; return ildvn; }
//'var_name': name of the variable, it is optional. VAR * VAR_MGR::register_var(CHAR const* var_name, UINT tyid, UINT align, UINT flag) { IS_TRUE0(var_name != NULL && tyid != 0); SYM * sym = m_ru_mgr->add_to_symtab(var_name); return register_var(sym, tyid, align, flag); }
/* Find preheader BB. If it does not exist, insert one before loop 'li'. 'insert_bb': return true if this function insert a new bb before loop, otherwise return false. 'force': force to insert preheader BB whatever it has exist. Return the new BB if insertion is successful. Note if we find the preheader, the last IR of it may be call. So if you are going to insert IR at the tail of preheader, the best is force to insert a new bb. */ IR_BB * find_and_insert_prehead(LI<IR_BB> const* li, REGION * ru, OUT bool & insert_bb, bool force) { IS_TRUE0(li && ru); insert_bb = false; IR_CFG * cfg = ru->get_cfg(); IR_BB_LIST * bblst = ru->get_bb_list(); IR_BB * head = LI_loop_head(li); C<IR_BB*> * bbholder = NULL; bblst->find(head, &bbholder); IS_TRUE0(bbholder); C<IR_BB*> * tt = bbholder; IR_BB * prev = bblst->get_prev(&tt); //Find appropriate BB to be prehead. bool find_appropriate_prev_bb = false; EDGE_C const* ec = VERTEX_in_list(cfg->get_vertex(IR_BB_id(head))); while (ec != NULL) { UINT pred = VERTEX_id(EDGE_from(EC_edge(ec))); if (pred == IR_BB_id(prev)) { find_appropriate_prev_bb = true; break; } ec = EC_next(ec); } if (!force && find_appropriate_prev_bb) { return prev; } LIST<IR_BB*> preds; cfg->get_preds(preds, head); insert_bb = true; IR_BB * newbb = ru->new_bb(); bblst->insert_before(newbb, bbholder); BITSET * loop_body = LI_bb_set(li); for (IR_BB * p = preds.get_head(); p != NULL; p = preds.get_next()) { if (loop_body->is_contain(IR_BB_id(p))) { continue; } cfg->add_bb(newbb); cfg->insert_vertex_between(IR_BB_id(p), IR_BB_id(head), IR_BB_id(newbb)); IR_BB_is_fallthrough(newbb) = 1; } return newbb; }