daa86443d8d5909aa7d4f649255fe1e895d7804e
[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/xprintf.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 arg_occ_t *occ) {
33   /* Firm objects are always pointer */
34   return arg_type_ptr;
35 }
36
37 static int firm_get_arg_type_int(const arg_occ_t *occ) {
38   return arg_type_int;
39 }
40
41
42 static int bitset_get_arg_type(const arg_occ_t *occ) {
43   return arg_type_ptr;
44 }
45
46 static int bitset_emit(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
47 {
48   int res = 2;
49   bitset_t *b = arg->v_ptr;
50   bitset_pos_t p;
51   char buf[32];
52   const char *prefix = "";
53
54   arg_append(app, occ, "[", 1);
55   for(p = bitset_next_set(b, 0); p != -1; p = bitset_next_set(b, p)) {
56     int n;
57
58     n = snprintf(buf, sizeof(buf), "%s%d", prefix, (int) p);
59     arg_append(app, occ, buf, n);
60     prefix = ", ";
61     res += n;
62   }
63   arg_append(app, occ, "]", 1);
64
65   return res;
66 }
67
68 /**
69  * emit an opaque Firm dbg_info object
70  */
71 static int firm_emit_dbg(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
72 {
73   char buf[1024];
74   ir_node *irn = arg->v_ptr;
75   dbg_info *dbg = get_irn_dbg_info(irn);
76
77   buf[0] = '\0';
78   if (dbg && __dbg_info_snprint) {
79     if (__dbg_info_snprint(buf, sizeof(buf), dbg) <= 0)
80       buf[0] = '\0';
81   }
82   return arg_append(app, occ, buf, strlen(buf));
83 }
84
85 /**
86  * emit a Firm object
87  */
88 static int firm_emit(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
89 {
90 #define A(s)    occ->flag_hash ? s " ": ""
91
92   void *X = arg->v_ptr;
93   firm_kind *obj = X;
94   int i, n;
95   ir_node *block;
96   char add[64];
97   char buf[256];
98   char tv[256];
99
100   buf[0] = '\0';
101   add[0] = '\0';
102
103   if (! X)
104     strncpy(buf, "(null)", sizeof(buf));
105   else {
106     switch (*obj) {
107     case k_BAD:
108       snprintf(buf, sizeof(buf), "BAD");
109       snprintf(add, sizeof(add), "[%p]", X);
110       break;
111     case k_entity:
112       snprintf(buf, sizeof(buf), "%s%s", A("ent"),
113           isupper(occ->conversion) ? get_entity_ld_name(X): get_entity_name(X));
114       snprintf(add, sizeof(add), "[%ld]", get_entity_nr(X));
115       break;
116     case k_type:
117       snprintf(buf, sizeof(buf), "%s%s:%s", A("type"), get_type_tpop_name(X), get_type_name(X));
118       snprintf(add, sizeof(add), "[%ld]", get_type_nr(X));
119       break;
120     case k_ir_graph:
121       snprintf(buf, sizeof(buf), "%s%s", A("irg"), get_entity_name(get_irg_entity(X)));
122       snprintf(add, sizeof(add), "[%ld]", get_irg_graph_nr(X));
123       break;
124     case k_ir_node:
125       switch (occ->conversion) {
126       case 'B':
127         block = is_no_Block(X) ? get_nodes_block(X) : X;
128         snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(block),
129             get_mode_name(get_irn_mode(block)));
130         snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(block));
131         break;
132       case 'N':
133         snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(X));
134         break;
135       default:
136         if (is_Const(X)) {
137           tarval_snprintf(tv, sizeof(tv), get_Const_tarval(X));
138           snprintf(buf, sizeof(buf), "%s%s%s<%s>", A("irn"), get_irn_opname(X),
139             get_mode_name(get_irn_mode(X)), tv);
140         }
141         else
142           snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(X),
143             get_mode_name(get_irn_mode(X)));
144         snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(X));
145       }
146       break;
147     case k_ir_mode:
148       snprintf(buf, sizeof(buf), "%s%s", A("mode"), get_mode_name(X));
149       break;
150     case k_tarval:
151       tarval_snprintf(tv, sizeof(tv), X);
152       snprintf(buf, sizeof(buf), "%s%s", A("tv"), tv);
153       break;
154     case k_ir_loop:
155       snprintf(buf, sizeof(buf), "ldepth[%d]", get_loop_depth(X));
156       break;
157     case k_ir_op:
158       snprintf(buf, sizeof(buf), "%s%s", A("op"), get_op_name(X));
159       break;
160     case k_ir_compound_graph_path:
161       strncat(buf, A("cgp"), sizeof(buf));
162
163       n = get_compound_graph_path_length(X);
164       for (i = 0; i < n; ++i) {
165         entity *ent = get_compound_graph_path_node(X, i);
166         strncat(buf, get_entity_name(ent), sizeof(buf));
167         if (i < n - 1)
168           strncat(buf, ".", sizeof(buf));
169       }
170       break;
171     default:
172       snprintf(buf, sizeof(buf), "UNKWN");
173       snprintf(add, sizeof(add), "[%p]", X);
174     }
175   }
176
177   if(occ->flag_plus)
178         strncat(buf, add, sizeof(buf));
179
180   return arg_append(app, occ, buf, strlen(buf));
181
182 #undef A
183 }
184
185 /**
186  * emit an ident
187  */
188 static int firm_emit_ident(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
189 {
190   ident *id = (ident *)arg->v_ptr;
191   const char *p = id ? get_id_str(id) : "(null)";
192
193   return arg_append(app, occ, p, strlen(p));
194 }
195
196 /**
197  * Emit indent.
198  */
199 static int firm_emit_indent(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
200 {
201         int i;
202         int amount = arg->v_int;
203
204         for(i = 0; i < amount; ++i)
205                 appendable_chadd(app, ' ');
206
207         return amount;
208 }
209
210 /**
211  * Emit pnc.
212  */
213 static int firm_emit_pnc(appendable_t *app, const arg_occ_t *occ, const arg_value_t *arg)
214 {
215   int value = arg->v_int;
216   const char *p = get_pnc_string(value);
217
218   return arg_append(app, occ, p, strlen(p));
219 }
220
221 arg_env_t *firm_get_arg_env(void)
222 {
223 #define X(name, letter) {"firm:" name, letter}
224
225   static arg_env_t *env = NULL;
226
227   static arg_handler_t firm_handler   = { firm_get_arg_type, firm_emit };
228   static arg_handler_t ident_handler  = { firm_get_arg_type, firm_emit_ident };
229   static arg_handler_t indent_handler = { firm_get_arg_type_int, firm_emit_indent };
230   static arg_handler_t pnc_handler    = { firm_get_arg_type_int, firm_emit_pnc };
231   static arg_handler_t bitset_handler = { bitset_get_arg_type, bitset_emit };
232   static arg_handler_t debug_handler  = { firm_get_arg_type, firm_emit_dbg };
233
234   static struct {
235     const char *name;
236     char letter;
237   } args[] = {
238     X("type",      't'),
239     X("entity",    'e'),
240     X("entity_ld", 'E'),
241     X("tarval",    'T'),
242     X("irn",       'n'),
243     X("op",        'O'),
244     X("irn_nr",    'N'),
245     X("mode",      'm'),
246     X("block",     'B'),
247     X("pnc",       '='),
248   };
249
250   int i;
251
252   if(env == NULL) {
253     env = arg_new_env();
254     arg_add_std(env);
255
256     arg_register(env, "firm", 'F', &firm_handler);
257     for (i = 0; i < sizeof(args)/sizeof(args[0]); ++i)
258       arg_register(env, args[i].name, args[i].letter, &firm_handler);
259
260     arg_register(env, "firm:ident", 'I', &ident_handler);
261     arg_register(env, "firm:indent", 'D', &indent_handler);
262     arg_register(env, "firm:pnc",      '=', &pnc_handler);
263     arg_register(env, "firm:dbg_info", 'g', &debug_handler);
264     /* arg_register(env, "firm:bitset", 'b', &bitset_handler); */
265   }
266
267   return env;
268 }