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