5ef2b18c6b97889c009e38e8e8097f75e9b39e79
[libfirm] / ir / st / exc.c
1 /* Copyright (c) 2002 by Universität Karlsruhe (TH).  All Rights Reserved */
2 //
3 // Time-stamp: <02/03/04 17:24:07 liekweg>
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           // ToDo: Check for proper Proj attr?!?
73           if ((op == op_Load) || (op == op_Store)  ||
74                   (op == op_Div ) || (op == op_Raise)  ||
75                   (op == op_Call) || (op == op_Alloc))
76                 return (true);
77         }
78   else
79         {
80           return (false);
81         }
82 }
83
84 /*
85 Return true iff the given node represents a normal cfg jump
86 */
87 static bool is_cfg_jmp (ir_node *node)
88 {
89   ir_op *op = get_irn_op (node);
90
91   if (op == op_Proj)
92         {
93           op = get_irn_op (get_Proj_pred (node));
94
95           // Proj_X (Proj_Cmp (Cond))
96           if (op_Proj == op)
97                 return (true);                  /* check for op == op_Cmp and op == op_Cond */
98         }
99
100   return (false);
101 }
102
103 /*
104  Return true iff a new exception region must be left upon entry of this block.
105
106  If all CFG preds of this block are exception jumps, then we must
107  return true.
108 */
109 bool is_handler_entry (ir_graph *graph, ir_node *block)
110 {
111   bool is_entry = true;
112   int  i        = 0;
113   int  n        = get_irn_arity (block);
114   ir_node *node = 0;
115   ir_op* op     = op_Bad;
116
117   if (exc_invalid == get_Block_exc (block))
118         {
119           for (i = 0; (i < n) && is_entry; i ++)
120                 if (is_exc_jmp (get_irn_n (block, i)))
121                   continue;
122                 else
123                   is_entry = false;
124
125           if (true == is_entry)
126                 set_Block_exc (block, exc_handler);
127         }
128
129   return (exc_handler == get_Block_exc (block));
130 }
131
132 /*
133  Return true iff a new exception region must be started upon entry of this block.
134
135  If this block immediately dominates a handler entry, we must return true.
136 */
137 bool is_region_entry  (ir_graph *graph, ir_node *block)
138 {
139   assert (0 && "Not implemented");
140
141   if (exc_invalid == get_Block_exc (block))
142         {
143           int i         = 0;
144           int n         = get_irn_n_outs (block);
145           ir_node *succ = 0;
146
147           bool no_handler = true;
148
149           for (i = 0; (i < n) && no_handler; i ++)
150                 {
151                   succ = get_irn_out (block, i);
152
153                   if (has_handler (graph, succ, block))
154                         no_handler = false;
155                 }
156
157           if (false == no_handler)
158                 set_Block_exc (block, exc_region);
159         }
160
161   return (exc_region == get_Block_exc (block));
162
163   return (TRUE);
164 }
165
166 /*
167  Return true iff this block is part of handler code.
168
169  If this block is dominated by a block for which {@link
170  is_handler_entry} is true, then this block is part of the handler.
171 */
172 bool is_handler_block (ir_graph *graph, ir_node *block)
173 {
174   assert (0 && "Not implemented");
175
176   if (exc_invalid == get_Block_exc (block))
177         {
178           bool no_handler = true;
179           dom_env_t *env  = get_dom_env (graph, block);
180           int block_index = env->index_a;
181           bs_t block_mask = 0x00000001 << block_index;
182           int n_blocks    = env->dt->n_blocks;
183           int i           = 0;
184
185           for (i = 0; (i < n_blocks) && no_handler; i ++)
186                 if (0 != (env->dt->masks [i] & block_mask)) /* if dominator */
187                   if (is_handler_entry (graph, env->dt->blocks [i])) /* is handler entry */
188                         no_handler = false;
189
190           delete_dom_env (env);
191
192           if (false == no_handler)
193                 set_Block_exc (block, exc_handler);
194         }
195
196   return (exc_handler == get_Block_exc (block));
197 }
198
199 /*
200   Convert a value of type exc_t to a descriptive string.
201   Returns a reference to a statically allocated, constant string.
202 */
203
204 const char *exc_to_string (exc_t exc)
205 {
206   int exc_val = (int) exc;
207
208   assert ((0 <= (int) exc_val) && (exc_val < (int) exc_max));
209
210   return (exc_strings [exc_val]);
211 }