*** empty log message ***
[libfirm] / ir / st / exc.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/st/exc.c
4  * Purpose:     Helper functions for jack exceptions.
5  * Author:      Florian Liekweg
6  * Modified by:
7  * Created:     4.3.2002
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2002-2003 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 /**
14    NAME
15      exc
16    PURPOSE
17      Helper functions for exceptions
18    S
19      not quite complete
20 ***/
21
22 # include "exc.h"
23
24 static char* exc_strings [] = {
25   "Invalid",                                    /* invalid */
26   "Normal",                                             /* normal */
27   "Entry",                                              /* entry to region */
28   "Exit",                                               /* exit of region */
29   "Handler",                                    /* entry to handler */
30   "Cont"
31 };
32
33
34 /*
35   Return true iff (block b is a handler entry AND a dominates b) OR
36   (b has a CFG successor that is both a handler entry AND is dominated
37   by a)
38 */
39 static bool has_handler (ir_graph *graph, ir_node *b, ir_node *a)
40 {
41   int i         = 0;
42   int n         = get_irn_n_outs (b);
43   ir_node *succ = 0;
44
45   assert (0 && "Wrongly implemented");
46   /* must check for _immediate_ dominance !!! */
47
48   if (is_handler_entry (graph, b) && dominates (graph, a, b))
49         return (true);
50
51   for (i = 0; i < n; i ++)
52         {
53           succ = get_irn_out (b, i);
54
55           if (has_handler (graph, succ, a))
56                 return (true);
57         }
58
59   return (false);
60 }
61
62 /*
63   Return true iff the given node represents an exception jump
64 */
65 static bool is_exc_jmp (ir_node *node)
66 {
67   ir_op *op = get_irn_op (node);
68
69   /* Proj_X (Load), Proj_X (Sto), Proj_X (Div_Int),
70      Proj_X (Raise), Proj_X (Call), Proj_X (Alloc) */
71   if (op == op_Proj)
72         {
73           op = get_irn_op (get_Proj_pred (node));
74
75           assert ((is_fragile_op(get_Proj_pred(node))) &&
76                   (op != op_Bad) /*&& (op != op_Unknown)*/ &&
77                   (get_irn_mode(node) == mode_X));/* Check for proper Proj attr */
78           return (true);
79         }
80   else
81         {
82           return (false);
83         }
84 }
85
86 /*
87 Return true iff the given node represents a normal cfg jump
88 */
89 #if 0
90 static bool is_cfg_jmp (ir_node *node)
91 {
92   ir_op *op = get_irn_op (node);
93
94   if (op == op_Proj)
95     {
96       op = get_irn_op (get_Proj_pred (node));
97
98       /* Proj_X (Proj_Cmp (Cond)) */
99       if (op_Proj == op)
100         return (true);  /* check for op == op_Cmp and op == op_Cond */
101     }
102
103   return (false);
104 }
105 #endif
106
107 void set_Block_exc(ir_node *n, exc_t exc) {
108 }
109
110 exc_t get_Block_exc(ir_node *n) {
111   return 0;
112 }
113
114
115 /* handler handling for Blocks */
116 void
117 set_Block_handler (ir_node *block, ir_node *handler)  {
118   assert (is_Block(block));
119   assert (is_Block(handler));
120 }
121
122 ir_node *
123 get_Block_handler (ir_node *block) {
124   assert (is_Block(block));
125   return (NULL);
126 }
127
128 /* handler handling for Nodes */
129 void
130 set_Node_handler (ir_node *node, ir_node *handler) {
131
132 }
133
134 ir_node *
135 get_Node_handler (ir_node *node) {
136   return (NULL);
137 }
138
139
140 /*
141  Return true iff a new exception region must be left upon entry of this block.
142
143  If all CFG preds of this block are exception jumps, then we must
144  return true.
145 */
146 bool is_handler_entry (ir_graph *graph, ir_node *block)
147 {
148   bool is_entry = true;
149   int  i        = 0;
150   int  n        = get_irn_arity (block);
151
152   if (exc_invalid == get_Block_exc (block))
153         {
154           for (i = 0; (i < n) && (is_entry == true); i ++)
155                 if (is_exc_jmp (get_irn_n (block, i)))
156                   continue;
157                 else
158                   is_entry = false;
159
160           if (true == is_entry)
161                 set_Block_exc (block, exc_handler);
162         }
163
164   return (exc_handler == get_Block_exc (block));
165 }
166
167 /*
168  Return true iff a new exception region must be started upon entry of this block.
169
170  If this block immediately dominates a handler entry, we must return true.
171 */
172 bool is_region_entry  (ir_graph *graph, ir_node *block)
173 {
174   assert (0 && "Not implemented");
175
176   if (exc_invalid == get_Block_exc (block))
177         {
178           int i         = 0;
179           int n         = get_irn_n_outs (block);
180           ir_node *succ = 0;
181
182           bool no_handler = true;
183
184           for (i = 0; (i < n) && (no_handler == true); i ++)
185                 {
186                   succ = get_irn_out (block, i);
187
188                   if (has_handler (graph, succ, block))
189                         no_handler = false;
190                 }
191
192           if (false == no_handler)
193                 set_Block_exc (block, exc_region);
194         }
195
196   return (exc_region == get_Block_exc (block));
197
198   return (true);
199 }
200
201 /*
202  Return true iff this block is part of handler code.
203
204  If this block is dominated by a block for which {@link
205  is_handler_entry} is true, then this block is part of the handler.
206 */
207 bool is_handler_block (ir_graph *graph, ir_node *block)
208 {
209   assert (0 && "Not implemented");
210
211   if (exc_invalid == get_Block_exc (block))
212         {
213           bool no_handler = true;
214           dom_env_t *env  = get_dom_env (graph, block);
215           int block_index = env->index_a;
216           bs_t block_mask = 0x00000001 << block_index;
217           int n_blocks    = env->dt->n_blocks;
218           int i           = 0;
219
220           for (i = 0; (i < n_blocks) && (no_handler == true); i ++)
221                 if (0 != (env->dt->masks [i] & block_mask)) /* if dominator */
222                   if (is_handler_entry (graph, env->dt->blocks [i])) /* is handler entry */
223                         no_handler = false;
224
225           delete_dom_env (env);
226
227           if (false == no_handler)
228                 set_Block_exc (block, exc_handler);
229         }
230
231   return (exc_handler == get_Block_exc (block));
232 }
233
234 /*
235   Convert a value of type exc_t to a descriptive string.
236   Returns a reference to a statically allocated, constant string.
237 */
238
239 const char *exc_to_string (exc_t exc)
240 {
241   int exc_val = (int) exc;
242
243   assert ((0 <= (int) exc_val) && (exc_val < (int) exc_max));
244
245   return (exc_strings [exc_val]);
246 }