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