properties updated
[libfirm] / ir / st / exc.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief     Helper functions for jack exceptions.
23  * @author    Florian Liekweg
24  * @date      4.3.2002
25  * @version   $Id$
26  */
27
28 /**
29    NAME
30      exc
31    PURPOSE
32      Helper functions for exceptions
33    S
34      not quite complete
35 ***/
36
37 #include <assert.h>
38 #include "exc.h"
39
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 */
46   "Cont"
47 };
48
49
50 /*
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
53   by a)
54 */
55 static bool has_handler (ir_graph *graph, ir_node *b, ir_node *a)
56 {
57   int i         = 0;
58   int n         = get_irn_n_outs (b);
59   ir_node *succ = 0;
60
61   assert (0 && "Wrongly implemented");
62   /* must check for _immediate_ dominance !!! */
63
64   if (is_handler_entry (graph, b) && dominates (graph, a, b))
65         return (true);
66
67   for (i = 0; i < n; i ++)
68         {
69           succ = get_irn_out (b, i);
70
71           if (has_handler (graph, succ, a))
72                 return (true);
73         }
74
75   return (false);
76 }
77
78 /*
79   Return true iff the given node represents an exception jump
80 */
81 static bool is_exc_jmp (ir_node *node)
82 {
83   ir_op *op = get_irn_op (node);
84
85   /* Proj_X (Load), Proj_X (Sto), Proj_X (Div_Int),
86      Proj_X (Raise), Proj_X (Call), Proj_X (Alloc) */
87   if (op == op_Proj)
88         {
89           op = get_irn_op (get_Proj_pred (node));
90
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 */
94           return (true);
95         }
96   else
97         {
98           return (false);
99         }
100 }
101
102 /*
103 Return true iff the given node represents a normal cfg jump
104 */
105 #if 0
106 static bool is_cfg_jmp (ir_node *node)
107 {
108   ir_op *op = get_irn_op (node);
109
110   if (op == op_Proj)
111     {
112       op = get_irn_op (get_Proj_pred (node));
113
114       /* Proj_X (Proj_Cmp (Cond)) */
115       if (op_Proj == op)
116         return (true);  /* check for op == op_Cmp and op == op_Cond */
117     }
118
119   return (false);
120 }
121 #endif
122
123 void set_Block_exc(ir_node *n, exc_t exc) {
124 }
125
126 exc_t get_Block_exc(ir_node *n) {
127   return 0;
128 }
129
130
131 /* handler handling for Blocks */
132 void
133 set_Block_handler (ir_node *block, ir_node *handler)  {
134   assert (is_Block(block));
135   assert (is_Block(handler));
136 }
137
138 ir_node *
139 get_Block_handler (ir_node *block) {
140   assert (is_Block(block));
141   return (NULL);
142 }
143
144 /* handler handling for Nodes */
145 void
146 set_Node_handler (ir_node *node, ir_node *handler) {
147
148 }
149
150 ir_node *
151 get_Node_handler (ir_node *node) {
152   return (NULL);
153 }
154
155
156 /*
157  Return true iff a new exception region must be left upon entry of this block.
158
159  If all CFG preds of this block are exception jumps, then we must
160  return true.
161 */
162 bool is_handler_entry (ir_graph *graph, ir_node *block)
163 {
164   bool is_entry = true;
165   int  i        = 0;
166   int  n        = get_irn_arity (block);
167
168   if (exc_invalid == get_Block_exc (block))
169         {
170           for (i = 0; (i < n) && (is_entry == true); i ++)
171                 if (is_exc_jmp (get_irn_n (block, i)))
172                   continue;
173                 else
174                   is_entry = false;
175
176           if (true == is_entry)
177                 set_Block_exc (block, exc_handler);
178         }
179
180   return (exc_handler == get_Block_exc (block));
181 }
182
183 /*
184  Return true iff a new exception region must be started upon entry of this block.
185
186  If this block immediately dominates a handler entry, we must return true.
187 */
188 bool is_region_entry  (ir_graph *graph, ir_node *block)
189 {
190   assert (0 && "Not implemented");
191
192   if (exc_invalid == get_Block_exc (block))
193         {
194           int i         = 0;
195           int n         = get_irn_n_outs (block);
196           ir_node *succ = 0;
197
198           bool no_handler = true;
199
200           for (i = 0; (i < n) && (no_handler == true); i ++)
201                 {
202                   succ = get_irn_out (block, i);
203
204                   if (has_handler (graph, succ, block))
205                         no_handler = false;
206                 }
207
208           if (false == no_handler)
209                 set_Block_exc (block, exc_region);
210         }
211
212   return (exc_region == get_Block_exc (block));
213
214   return (true);
215 }
216
217 /*
218  Return true iff this block is part of handler code.
219
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.
222 */
223 bool is_handler_block (ir_graph *graph, ir_node *block)
224 {
225   assert (0 && "Not implemented");
226
227   if (exc_invalid == get_Block_exc (block))
228         {
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;
234           int i           = 0;
235
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 */
239                         no_handler = false;
240
241           delete_dom_env (env);
242
243           if (false == no_handler)
244                 set_Block_exc (block, exc_handler);
245         }
246
247   return (exc_handler == get_Block_exc (block));
248 }
249
250 /*
251   Convert a value of type exc_t to a descriptive string.
252   Returns a reference to a statically allocated, constant string.
253 */
254
255 const char *exc_to_string (exc_t exc)
256 {
257   int exc_val = (int) exc;
258
259   assert ((0 <= (int) exc_val) && (exc_val < (int) exc_max));
260
261   return (exc_strings [exc_val]);
262 }