/** * Block-walker, remove Bad block predecessors and shorten Phis. * Phi links must be up-to-date. */ static void block_remove_bads(ir_node *block) { /* 1. Create a new block without Bad inputs */ ir_graph *irg = get_irn_irg(block); const int max = get_Block_n_cfgpreds(block); ir_node **new_in = ALLOCAN(ir_node*, max); unsigned new_max = 0; for (int i = 0; i < max; ++i) { ir_node *const block_pred = get_Block_cfgpred(block, i); if (!is_Bad(block_pred)) { new_in[new_max++] = block_pred; } } /* If the end block is unreachable, it might have zero predecessors. */ if (new_max == 0) { ir_node *end_block = get_irg_end_block(irg); if (block == end_block) { set_irn_in(block, new_max, new_in); return; } } dbg_info *dbgi = get_irn_dbg_info(block); ir_node *new_block = new_rd_Block(dbgi, irg, new_max, new_in); ir_entity *block_entity = get_Block_entity(block); set_Block_entity(new_block, block_entity); /* 2. Remove inputs on Phis, where the block input is Bad. */ for (ir_node *phi = get_Block_phis(block), *next; phi != NULL; phi = next) { next = get_Phi_next(phi); assert(get_irn_arity(phi) == max); unsigned j = 0; foreach_irn_in(phi, i, pred) { ir_node *const block_pred = get_Block_cfgpred(block, i); if (!is_Bad(block_pred)) { new_in[j++] = pred; } } assert(j == new_max); /* shortcut if only 1 phi input is left */ if (new_max == 1) { ir_node *new_node = new_in[0]; /* can happen inside unreachable endless loops */ if (new_node == phi) return; if (get_Phi_loop(phi)) remove_keep_alive(phi); exchange(phi, new_node); } else { set_irn_in(phi, new_max, new_in); } }
/** * Pre-block-walker: calculate the control dependence */ static void cdep_pre(ir_node *node, void *ctx) { (void)ctx; for (int i = get_Block_n_cfgpreds(node); i-- > 0; ) { ir_node *pred = get_Block_cfgpred_block(node, i); if (is_Bad(pred)) continue; ir_node *pdom = get_Block_ipostdom(pred); for (ir_node *dependee = node; dependee != pdom; dependee = get_Block_ipostdom(dependee)) { assert(!is_Bad(pdom)); add_cdep(dependee, pred); } } }
/** * Get the predecessor block. */ static ir_node *get_block_n(const ir_node *block, int pos) { ir_node *cfgpred = get_cf_op(get_Block_cfgpred(block, pos)); if (is_Bad(cfgpred)) return NULL; return get_nodes_block(cfgpred); }
int Socket::write( const char* pBuf, int nLen,int p_itime_out) { int iLeft = nLen,i_timeleft=p_itime_out; time_t t_start = time(NULL); while( iLeft > 0 ) { int i = ::send( m_nSock, pBuf, iLeft,0); if( i <= 0 ) return -1; iLeft -= i; pBuf += i; if(iLeft <=0|| i_timeleft<=0) break; do { fd_set events; struct timeval tm; FD_ZERO(&events); FD_SET(m_nSock, &events); tm.tv_sec = i_timeleft; tm.tv_usec = 0; while ((i = select(m_nSock+1, NULL,&events, NULL, &tm)) < 0 && errno == EINTR); if( i < 0 ) return -1; if(FD_ISSET(m_nSock,&events)) break; i_timeleft = t_start+p_itime_out - time(NULL); if(i==0&&is_Bad()) return -1; } while (i_timeleft >0) ; } return ( nLen - iLeft); }
/** * Check, whether a Return can be moved on block upwards. * * In a block with a Return, all live nodes must be linked * with the Return, otherwise they are dead (because the Return leaves * the graph, so no more users of the other nodes can exists. * * We can move a Return, if its predecessors are Phi nodes or * comes from another block. In the later case, it is always possible * to move the Return one block up, because the predecessor block must * dominate the Return block (SSA) and then it dominates the predecessor * block of the Return block as well. * * All predecessors of the Return block must be Jmp's of course, or we * cannot move it up, so we add blocks if needed. */ static bool can_move_ret(ir_node *ret) { ir_node *retbl = get_nodes_block(ret); int i, n = get_irn_arity(ret); for (i = 0; i < n; ++i) { ir_node *pred = get_irn_n(ret, i); if (! is_Phi(pred) && retbl == get_nodes_block(pred)) { /* first condition failed, found a non-Phi predecessor * then is in the Return block */ return false; } } /* check, that predecessors are Jmps */ n = get_Block_n_cfgpreds(retbl); /* we cannot move above a labeled block, as this might kill the block */ if (n <= 1 || get_Block_entity(retbl) != NULL) return false; for (i = 0; i < n; ++i) { ir_node *pred = get_Block_cfgpred(retbl, i); pred = skip_Tuple(pred); if (! is_Jmp(pred) && !is_Bad(pred)) { /* simply place a new block here */ ir_graph *irg = get_irn_irg(retbl); ir_node *block = new_r_Block(irg, 1, &pred); ir_node *jmp = new_r_Jmp(block); set_Block_cfgpred(retbl, i, jmp); } } return true; }
/** * a vcg attribute hook */ static int stat_dag_mark_hook(FILE *F, const ir_node *n, const ir_node *l) { static const char *colors[] = { "purple", "pink", "lightblue", "orange", "khaki", "orchid", "lilac", "turquoise" }; dag_entry_t *entry; /* do not count Bad / NoMem */ if (l) { if (is_NoMem(l) || is_Bad(l)) return DEFAULT_RET; /* check for additional options */ if (mark_options & FIRMSTAT_LOAD_IS_LEAVE && is_Load(n)) return DEFAULT_RET; if (mark_options & FIRMSTAT_CALL_IS_LEAVE && is_Call(n)) return DEFAULT_RET; } entry = get_irn_dag_entry(n); if (! entry) return DEFAULT_RET; fprintf(F, "color: %s info3: \"DAG id: %u\"", colors[entry->id & 7], entry->id); /* I know the color! */ return COLOR_RET; }
/* Walks back from n until it finds a real cf op. */ static ir_node *get_cf_op(ir_node *n) { while (!is_cfop(n) && !is_fragile_op(n) && !is_Bad(n)) { n = skip_Tuple(n); n = skip_Proj(n); } return n; }
/** * This function returns the last definition of a value. In case * this value was last defined in a previous block, Phi nodes are * inserted. If the part of the firm graph containing the definition * is not yet constructed, a dummy Phi node is returned. * * @param block the current block * @param pos the value number of the value searched * @param mode the mode of this value (needed for Phi construction) */ static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode) { ir_node *res = block->attr.block.graph_arr[pos]; if (res != NULL) return res; /* in a matured block we can immediately determine the phi arguments */ if (get_Block_matured(block)) { ir_graph *const irg = get_irn_irg(block); int const arity = get_irn_arity(block); /* no predecessors: use unknown value */ if (arity == 0) { if (block == get_irg_start_block(irg)) { if (default_initialize_local_variable != NULL) { ir_node *rem = get_r_cur_block(irg); set_r_cur_block(irg, block); res = default_initialize_local_variable(irg, mode, pos - 1); set_r_cur_block(irg, rem); } else { res = new_r_Unknown(irg, mode); } } else { goto bad; /* unreachable block, use Bad */ } /* one predecessor just use its value */ } else if (arity == 1) { ir_node *cfgpred = get_Block_cfgpred(block, 0); if (is_Bad(cfgpred)) { bad: res = new_r_Bad(irg, mode); } else { ir_node *cfgpred_block = get_nodes_block(cfgpred); res = get_r_value_internal(cfgpred_block, pos, mode); } } else { /* multiple predecessors construct Phi */ res = new_rd_Phi0(NULL, block, mode, pos); /* enter phi0 into our variable value table to break cycles * arising from set_phi_arguments */ block->attr.block.graph_arr[pos] = res; res = set_phi_arguments(res, pos); } } else { /* in case of immature block we have to keep a Phi0 */ res = new_rd_Phi0(NULL, block, mode, pos); /* enqueue phi so we can set arguments once the block matures */ res->attr.phi.next = block->attr.block.phis; block->attr.block.phis = res; } block->attr.block.graph_arr[pos] = res; return res; }
/* * Normalize the Returns of a graph by moving * the Returns upwards as much as possible. * This might be preferred for code generation. * * In pseudocode, it means: * * if (a) * res = b; * else * res = c; * return res; * * is transformed into * * if (a) * return b; * else * return c; */ void normalize_n_returns(ir_graph *irg) { int i, j, n; ir_node *list = NULL; ir_node *final = NULL; unsigned n_rets = 0; unsigned n_finals = 0; ir_node *endbl = get_irg_end_block(irg); int n_ret_vals; ir_node **in; ir_node *end; /* * First, link all returns: * These must be predecessors of the endblock. * Place Returns that can be moved on list, all others * on final. */ n = get_Block_n_cfgpreds(endbl); for (i = 0; i < n; ++i) { ir_node *ret = get_Block_cfgpred(endbl, i); if (is_Bad(ret)) { continue; } else if (is_Return(ret) && can_move_ret(ret)) { /* * Ok, all conditions met, we can move this Return, put it * on our work list. */ set_irn_link(ret, list); list = ret; ++n_rets; } else { /* Put all nodes that are not changed on the final list. */ set_irn_link(ret, final); final = ret; ++n_finals; } }