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