2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Helper functions for jack exceptions.
23 * @author Florian Liekweg
32 Helper functions for exceptions
40 static char* exc_strings [] = {
41 "Invalid", /* invalid */
42 "Normal", /* normal */
43 "Entry", /* entry to region */
44 "Exit", /* exit of region */
45 "Handler", /* entry to handler */
51 Return true iff (block b is a handler entry AND a dominates b) OR
52 (b has a CFG successor that is both a handler entry AND is dominated
55 static bool has_handler (ir_graph *graph, ir_node *b, ir_node *a)
58 int n = get_irn_n_outs (b);
61 assert (0 && "Wrongly implemented");
62 /* must check for _immediate_ dominance !!! */
64 if (is_handler_entry (graph, b) && dominates (graph, a, b))
67 for (i = 0; i < n; i ++)
69 succ = get_irn_out (b, i);
71 if (has_handler (graph, succ, a))
79 Return true iff the given node represents an exception jump
81 static bool is_exc_jmp (ir_node *node)
83 ir_op *op = get_irn_op (node);
85 /* Proj_X (Load), Proj_X (Sto), Proj_X (Div_Int),
86 Proj_X (Raise), Proj_X (Call), Proj_X (Alloc) */
89 op = get_irn_op (get_Proj_pred (node));
91 assert ((is_fragile_op(get_Proj_pred(node))) &&
92 (op != op_Bad) /*&& (op != op_Unknown)*/ &&
93 (get_irn_mode(node) == mode_X));/* Check for proper Proj attr */
103 Return true iff the given node represents a normal cfg jump
106 static bool is_cfg_jmp (ir_node *node)
108 ir_op *op = get_irn_op (node);
112 op = get_irn_op (get_Proj_pred (node));
114 /* Proj_X (Proj_Cmp (Cond)) */
116 return (true); /* check for op == op_Cmp and op == op_Cond */
123 void set_Block_exc(ir_node *n, exc_t exc) {
126 exc_t get_Block_exc(ir_node *n) {
131 /* handler handling for Blocks */
133 set_Block_handler (ir_node *block, ir_node *handler) {
134 assert (is_Block(block));
135 assert (is_Block(handler));
139 get_Block_handler (ir_node *block) {
140 assert (is_Block(block));
144 /* handler handling for Nodes */
146 set_Node_handler (ir_node *node, ir_node *handler) {
151 get_Node_handler (ir_node *node) {
157 Return true iff a new exception region must be left upon entry of this block.
159 If all CFG preds of this block are exception jumps, then we must
162 bool is_handler_entry (ir_graph *graph, ir_node *block)
164 bool is_entry = true;
166 int n = get_irn_arity (block);
168 if (exc_invalid == get_Block_exc (block))
170 for (i = 0; (i < n) && (is_entry == true); i ++)
171 if (is_exc_jmp (get_irn_n (block, i)))
176 if (true == is_entry)
177 set_Block_exc (block, exc_handler);
180 return (exc_handler == get_Block_exc (block));
184 Return true iff a new exception region must be started upon entry of this block.
186 If this block immediately dominates a handler entry, we must return true.
188 bool is_region_entry (ir_graph *graph, ir_node *block)
190 assert (0 && "Not implemented");
192 if (exc_invalid == get_Block_exc (block))
195 int n = get_irn_n_outs (block);
198 bool no_handler = true;
200 for (i = 0; (i < n) && (no_handler == true); i ++)
202 succ = get_irn_out (block, i);
204 if (has_handler (graph, succ, block))
208 if (false == no_handler)
209 set_Block_exc (block, exc_region);
212 return (exc_region == get_Block_exc (block));
218 Return true iff this block is part of handler code.
220 If this block is dominated by a block for which {@link
221 is_handler_entry} is true, then this block is part of the handler.
223 bool is_handler_block (ir_graph *graph, ir_node *block)
225 assert (0 && "Not implemented");
227 if (exc_invalid == get_Block_exc (block))
229 bool no_handler = true;
230 dom_env_t *env = get_dom_env (graph, block);
231 int block_index = env->index_a;
232 bs_t block_mask = 0x00000001 << block_index;
233 int n_blocks = env->dt->n_blocks;
236 for (i = 0; (i < n_blocks) && (no_handler == true); i ++)
237 if (0 != (env->dt->masks [i] & block_mask)) /* if dominator */
238 if (is_handler_entry (graph, env->dt->blocks [i])) /* is handler entry */
241 delete_dom_env (env);
243 if (false == no_handler)
244 set_Block_exc (block, exc_handler);
247 return (exc_handler == get_Block_exc (block));
251 Convert a value of type exc_t to a descriptive string.
252 Returns a reference to a statically allocated, constant string.
255 const char *exc_to_string (exc_t exc)
257 int exc_val = (int) exc;
259 assert ((0 <= (int) exc_val) && (exc_val < (int) exc_max));
261 return (exc_strings [exc_val]);