80d9404b68cea3469b16e2433eeb28d832578c1d
[libfirm] / ir / ir / irargs.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/irargs.c
4  * Purpose:     Support for libcore IR object output.
5  * Author:      Sebastian Hack
6  * Modified by:
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2005 Universitaet Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include "bitset.h"
18
19 #include <ctype.h>
20 #include <libcore/lc_printf.h>
21
22 #include "firm_common.h"
23 #include "irnode_t.h"
24 #include "entity_t.h"
25 #include "irloop_t.h"
26 #include "tv_t.h"
27 #include "dbginfo_t.h"
28
29 /**
30  * identify a firm object type
31  */
32 static int firm_get_arg_type(const lc_arg_occ_t *occ) {
33   /* Firm objects are always pointer */
34   return lc_arg_type_ptr;
35 }
36
37 static int firm_get_arg_type_int(const lc_arg_occ_t *occ) {
38   return lc_arg_type_int;
39 }
40
41
42 static int bitset_get_arg_type(const lc_arg_occ_t *occ) {
43   return lc_arg_type_ptr;
44 }
45
46 static int bitset_emit(lc_appendable_t *app,
47     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
48 {
49   int res = 2;
50   bitset_t *b = arg->v_ptr;
51   bitset_pos_t p;
52   char buf[32];
53   const char *prefix = "";
54
55   lc_arg_append(app, occ, "[", 1);
56   for(p = bitset_next_set(b, 0); p != -1; p = bitset_next_set(b, p)) {
57     int n;
58
59     n = snprintf(buf, sizeof(buf), "%s%d", prefix, (int) p);
60     lc_arg_append(app, occ, buf, n);
61     prefix = ", ";
62     res += n;
63   }
64   lc_arg_append(app, occ, "]", 1);
65
66   return res;
67 }
68
69 /**
70  * emit an opaque Firm dbg_info object
71  */
72 static int firm_emit_dbg(lc_appendable_t *app,
73     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
74 {
75   char buf[1024];
76   ir_node *irn = arg->v_ptr;
77   dbg_info *dbg = get_irn_dbg_info(irn);
78
79   buf[0] = '\0';
80   if (dbg && __dbg_info_snprint) {
81     if (__dbg_info_snprint(buf, sizeof(buf), dbg) <= 0)
82       buf[0] = '\0';
83   }
84   return lc_arg_append(app, occ, buf, strlen(buf));
85 }
86
87 /**
88  * emit a Firm object
89  */
90 static int firm_emit(lc_appendable_t *app,
91     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
92 {
93 #define A(s)    occ->flag_hash ? s " ": ""
94
95   void *X = arg->v_ptr;
96   firm_kind *obj = X;
97   int i, n;
98   ir_node *block;
99   char add[64];
100   char buf[256];
101   char tv[256];
102   entity *ent;
103
104   buf[0] = '\0';
105   add[0] = '\0';
106
107   if (! X)
108     strncpy(buf, "(null)", sizeof(buf));
109   else {
110     switch (*obj) {
111     case k_BAD:
112       snprintf(buf, sizeof(buf), "BAD");
113       snprintf(add, sizeof(add), "[%p]", X);
114       break;
115     case k_entity:
116       snprintf(buf, sizeof(buf), "%s%s", A("ent"),
117           isupper(occ->conversion) ? get_entity_ld_name(X): get_entity_name(X));
118       snprintf(add, sizeof(add), "[%ld]", get_entity_nr(X));
119       break;
120     case k_type:
121       snprintf(buf, sizeof(buf), "%s%s:%s", A("type"), get_type_tpop_name(X), get_type_name(X));
122       snprintf(add, sizeof(add), "[%ld]", get_type_nr(X));
123       break;
124     case k_ir_graph:
125       snprintf(buf, sizeof(buf), "%s%s", A("irg"), get_entity_name(get_irg_entity(X)));
126       snprintf(add, sizeof(add), "[%ld]", get_irg_graph_nr(X));
127       break;
128     case k_ir_node:
129       switch (occ->conversion) {
130       case 'B':
131         block = is_no_Block(X) ? get_nodes_block(X) : X;
132         snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(block),
133             get_mode_name(get_irn_mode(block)));
134         snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(block));
135         break;
136       case 'N':
137         snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(X));
138         break;
139       default:
140         if (is_Const(X)) {
141           tarval_snprintf(tv, sizeof(tv), get_Const_tarval(X));
142           snprintf(buf, sizeof(buf), "%s%s%s<%s>", A("irn"), get_irn_opname(X),
143             get_mode_name(get_irn_mode(X)), tv);
144         }
145         else
146           snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(X),
147             get_mode_name(get_irn_mode(X)));
148         snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(X));
149       }
150       break;
151     case k_ir_mode:
152       snprintf(buf, sizeof(buf), "%s%s", A("mode"), get_mode_name(X));
153       break;
154     case k_tarval:
155       tarval_snprintf(tv, sizeof(tv), X);
156       snprintf(buf, sizeof(buf), "%s%s", A("tv"), tv);
157       break;
158     case k_ir_loop:
159       snprintf(buf, sizeof(buf), "ldepth[%d]", get_loop_depth(X));
160       break;
161     case k_ir_op:
162       snprintf(buf, sizeof(buf), "%s%s", A("op"), get_op_name(X));
163       break;
164     case k_ir_compound_graph_path:
165       n = get_compound_graph_path_length(X);
166
167       for (i = 0; i < n; ++i) {
168         ent = get_compound_graph_path_node(X, i);
169
170         strncat(buf, ".", sizeof(buf));
171         strncat(buf, get_entity_name(ent), sizeof(buf));
172         if (is_Array_type(get_entity_owner(ent))) {
173           snprintf(add, sizeof(add), "[%d]",
174             get_compound_graph_path_array_index(X, i));
175           strncat(buf, add, sizeof(buf));
176         }
177       }
178       add[0] = '\0';
179       break;
180
181     default:
182       snprintf(buf, sizeof(buf), "UNKWN");
183       snprintf(add, sizeof(add), "[%p]", X);
184     }
185   }
186
187   if (occ->flag_plus)
188         strncat(buf, add, sizeof(buf));
189
190   return lc_arg_append(app, occ, buf, strlen(buf));
191
192 #undef A
193 }
194
195 /**
196  * emit an ident
197  */
198 static int firm_emit_ident(lc_appendable_t *app,
199     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
200 {
201   ident *id = (ident *)arg->v_ptr;
202   const char *p = id ? get_id_str(id) : "(null)";
203
204   return lc_arg_append(app, occ, p, strlen(p));
205 }
206
207 /**
208  * Emit indent.
209  */
210 static int firm_emit_indent(lc_appendable_t *app,
211     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
212 {
213         int i;
214         int amount = arg->v_int;
215
216         for(i = 0; i < amount; ++i)
217                 lc_appendable_chadd(app, ' ');
218
219         return amount;
220 }
221
222 /**
223  * Emit pnc.
224  */
225 static int firm_emit_pnc(lc_appendable_t *app,
226     const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
227 {
228   int value = arg->v_int;
229   const char *p = get_pnc_string(value);
230
231   return lc_arg_append(app, occ, p, strlen(p));
232 }
233
234 lc_arg_env_t *firm_get_arg_env(void)
235 {
236 #define X(name, letter) {"firm:" name, letter}
237
238   static lc_arg_env_t *env = NULL;
239
240   static lc_arg_handler_t firm_handler   = { firm_get_arg_type, firm_emit };
241   static lc_arg_handler_t ident_handler  = { firm_get_arg_type, firm_emit_ident };
242   static lc_arg_handler_t indent_handler = { firm_get_arg_type_int, firm_emit_indent };
243   static lc_arg_handler_t pnc_handler    = { firm_get_arg_type_int, firm_emit_pnc };
244   static lc_arg_handler_t bitset_handler = { bitset_get_arg_type, bitset_emit };
245   static lc_arg_handler_t debug_handler  = { firm_get_arg_type, firm_emit_dbg };
246
247   static struct {
248     const char *name;
249     char letter;
250   } args[] = {
251     X("type",      't'),
252     X("entity",    'e'),
253     X("entity_ld", 'E'),
254     X("tarval",    'T'),
255     X("irn",       'n'),
256     X("op",        'O'),
257     X("irn_nr",    'N'),
258     X("mode",      'm'),
259     X("block",     'B'),
260     X("pnc",       '='),
261     X("cg_path",   'P'),
262   };
263
264   int i;
265
266   if(env == NULL) {
267     env = lc_arg_new_env();
268     lc_arg_add_std(env);
269
270     lc_arg_register(env, "firm", 'F', &firm_handler);
271     for (i = 0; i < sizeof(args)/sizeof(args[0]); ++i)
272       lc_arg_register(env, args[i].name, args[i].letter, &firm_handler);
273
274     lc_arg_register(env, "firm:ident", 'I', &ident_handler);
275     lc_arg_register(env, "firm:indent", 'D', &indent_handler);
276     lc_arg_register(env, "firm:pnc",      '=', &pnc_handler);
277     lc_arg_register(env, "firm:dbg_info", 'G', &debug_handler);
278     /* lc_arg_register(env, "firm:bitset", 'b', &bitset_handler); */
279   }
280
281   return env;
282 }