irargs.c 7.95 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
24
/**
 * @file
 * @brief    Support for libcore IR object output.
 * @author   Sebastian Hack
 * @version  $Id$
25
26
27
28
29
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

30
31
#include "bitset.h"

32
33
#include <ctype.h>

Matthias Braun's avatar
Matthias Braun committed
34
#include "lc_printf.h"
35
#include "firm_common.h"
36
37
38
39
#include "irnode_t.h"
#include "entity_t.h"
#include "irloop_t.h"
#include "tv_t.h"
40
#include "dbginfo_t.h"
41
42
43
44

/**
 * identify a firm object type
 */
Sebastian Hack's avatar
Sebastian Hack committed
45
static int firm_get_arg_type(const lc_arg_occ_t *occ) {
Michael Beck's avatar
Michael Beck committed
46
47
48
	(void) occ;
	/* Firm objects are always pointer */
	return lc_arg_type_ptr;
49
50
}

Sebastian Hack's avatar
Sebastian Hack committed
51
static int firm_get_arg_type_int(const lc_arg_occ_t *occ) {
Michael Beck's avatar
Michael Beck committed
52
53
	(void) occ;
	return lc_arg_type_int;
54
55
}

56

Sebastian Hack's avatar
Sebastian Hack committed
57
static int bitset_get_arg_type(const lc_arg_occ_t *occ) {
Michael Beck's avatar
Michael Beck committed
58
59
	(void) occ;
	return lc_arg_type_ptr;
60
61
}

Sebastian Hack's avatar
Sebastian Hack committed
62
63
static int bitset_emit(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
64
{
Michael Beck's avatar
Michael Beck committed
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
	int res = 2;
	bitset_t *b = arg->v_ptr;
	bitset_pos_t p;
	char buf[32];
	const char *prefix = "";

	lc_arg_append(app, occ, "[", 1);
	bitset_foreach(b, p) {
		int n;

		n = snprintf(buf, sizeof(buf), "%s%d", prefix, (int) p);
		lc_arg_append(app, occ, buf, n);
		prefix = ", ";
		res += n;
	}
	lc_arg_append(app, occ, "]", 1);

	return res;
83
84
}

85
86
87
/**
 * emit an opaque Firm dbg_info object
 */
Sebastian Hack's avatar
Sebastian Hack committed
88
89
static int firm_emit_dbg(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
90
{
Michael Beck's avatar
Michael Beck committed
91
92
93
94
95
96
97
98
99
100
	char buf[1024];
	ir_node *irn = arg->v_ptr;
	dbg_info *dbg = get_irn_dbg_info(irn);

	buf[0] = '\0';
	if (dbg && __dbg_info_snprint) {
		if (__dbg_info_snprint(buf, sizeof(buf), dbg) <= 0)
			buf[0] = '\0';
	}
	return lc_arg_append(app, occ, buf, strlen(buf));
101
102
}

103
104
105
/**
 * Beware: do not set the entity ld_name
 */
106
static const char *get_entity_ld_name_ex(ir_entity *ent) {
Michael Beck's avatar
Michael Beck committed
107
108
109
	if (ent->ld_name)
		return get_entity_ld_name(ent);
	return get_entity_name(ent);
110
111
}

112
113
114
/**
 * emit a Firm object
 */
Sebastian Hack's avatar
Sebastian Hack committed
115
116
static int firm_emit(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
117
{
118
#define A(s)    occ->flag_hash ? s " ": ""
119

Michael Beck's avatar
Michael Beck committed
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
	void *X = arg->v_ptr;
	firm_kind *obj = X;
	int i, n;
	ir_node *block;
	char add[64];
	char buf[256];
	char tv_buf[256];
	ir_entity *ent;

	buf[0] = '\0';
	add[0] = '\0';

	if (! X)
		strncpy(buf, "(null)", sizeof(buf));
	else {
		switch (*obj) {
	case k_BAD:
		snprintf(buf, sizeof(buf), "BAD");
		snprintf(add, sizeof(add), "[%p]", X);
		break;
	case k_entity:
		snprintf(buf, sizeof(buf), "%s%s", A("ent"),
			isupper(occ->conversion) ? get_entity_ld_name_ex(X): get_entity_name(X));
		snprintf(add, sizeof(add), "[%ld]", get_entity_nr(X));
		break;
	case k_type:
		snprintf(buf, sizeof(buf), "%s%s:%s", A("type"), get_type_tpop_name(X), get_type_name(X));
		snprintf(add, sizeof(add), "[%ld]", get_type_nr(X));
		break;
	case k_ir_graph:
		if (X == get_const_code_irg())
			snprintf(buf, sizeof(buf), "%s<ConstCodeIrg>", A("irg"));
		else
			snprintf(buf, sizeof(buf), "%s%s", A("irg"), get_entity_name(get_irg_entity(X)));
		snprintf(add, sizeof(add), "[%ld]", get_irg_graph_nr(X));
		break;
	case k_ir_node:
		switch (occ->conversion) {
		case 'B':
			block = is_no_Block(X) ? get_nodes_block(X) : X;
			snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(block),
				get_mode_name(get_irn_mode(block)));
			snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(block));
			break;
		case 'N':
			snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(X));
			break;
		default:
			if (is_Const(X)) {
				tarval *tv = get_Const_tarval(X);
				if (tv)
					tarval_snprintf(tv_buf, sizeof(tv_buf), tv);
				else
					strncpy(tv_buf, "(NULL)", sizeof(tv_buf));
				snprintf(buf, sizeof(buf), "%s%s%s<%s>", A("irn"), get_irn_opname(X),
					get_mode_name(get_irn_mode(X)), tv_buf);
			}
			else
				snprintf(buf, sizeof(buf), "%s%s%s", A("irn"), get_irn_opname(X),
				get_mode_name(get_irn_mode(X)));
			snprintf(add, sizeof(add), "[%ld:%d]", get_irn_node_nr(X), get_irn_idx(X));
			}
			break;
	case k_ir_mode:
		snprintf(buf, sizeof(buf), "%s%s", A("mode"), get_mode_name(X));
		break;
	case k_tarval:
		tarval_snprintf(tv_buf, sizeof(tv_buf), X);
		snprintf(buf, sizeof(buf), "%s%s", A("tv"), tv_buf);
		break;
	case k_ir_loop:
		snprintf(buf, sizeof(buf), "loop[%d:%d]", get_loop_loop_nr(X), get_loop_depth(X));
		break;
	case k_ir_op:
		snprintf(buf, sizeof(buf), "%s%s", A("op"), get_op_name(X));
		break;
	case k_ir_compound_graph_path:
		n = get_compound_graph_path_length(X);

		for (i = 0; i < n; ++i) {
			ent = get_compound_graph_path_node(X, i);

			strncat(buf, ".", sizeof(buf));
			strncat(buf, get_entity_name(ent), sizeof(buf));
			if (is_Array_type(get_entity_owner(ent))) {
				snprintf(add, sizeof(add), "[%d]",
					get_compound_graph_path_array_index(X, i));
				strncat(buf, add, sizeof(buf));
			}
		}
		add[0] = '\0';
		break;
	case k_ir_extblk:
		snprintf(buf, sizeof(buf), "ExtBlock");
		snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(get_extbb_leader(X)));
		break;

	default:
		snprintf(buf, sizeof(buf), "UNKWN");
		snprintf(add, sizeof(add), "[%p]", X);
		}
	}

	if (occ->flag_plus)
		strncat(buf, add, sizeof(buf));

	return lc_arg_append(app, occ, buf, strlen(buf));
227
228
229
230
231
232
233

#undef A
}

/**
 * emit an ident
 */
Sebastian Hack's avatar
Sebastian Hack committed
234
235
static int firm_emit_ident(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
236
{
Michael Beck's avatar
Michael Beck committed
237
238
	ident *id = (ident *)arg->v_ptr;
	const char *p = id ? get_id_str(id) : "(null)";
239

Michael Beck's avatar
Michael Beck committed
240
	return lc_arg_append(app, occ, p, strlen(p));
241
242
}

243
244
245
/**
 * Emit indent.
 */
Sebastian Hack's avatar
Sebastian Hack committed
246
247
static int firm_emit_indent(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
248
249
{
	int i;
Sebastian Hack's avatar
Sebastian Hack committed
250
251
	int width  = occ->width > 0 ? occ->width : 1;
	int amount = arg->v_int * width;
252

Michael Beck's avatar
Michael Beck committed
253
	for (i = 0; i < amount; ++i)
Sebastian Hack's avatar
Sebastian Hack committed
254
		lc_appendable_chadd(app, (i % width) == 0 ? '|' : ' ');
255
256
257
258

	return amount;
}

259
260
261
/**
 * Emit pnc.
 */
Sebastian Hack's avatar
Sebastian Hack committed
262
263
static int firm_emit_pnc(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
264
{
Michael Beck's avatar
Michael Beck committed
265
266
	int value = arg->v_int;
	const char *p = get_pnc_string(value);
267

Michael Beck's avatar
Michael Beck committed
268
	return lc_arg_append(app, occ, p, strlen(p));
269
270
}

Sebastian Hack's avatar
Sebastian Hack committed
271
lc_arg_env_t *firm_get_arg_env(void)
272
273
{

Michael Beck's avatar
Michael Beck committed
274
	static lc_arg_env_t *env = NULL;
275

Michael Beck's avatar
Michael Beck committed
276
277
278
279
280
281
	static lc_arg_handler_t firm_handler   = { firm_get_arg_type, firm_emit };
	static lc_arg_handler_t ident_handler  = { firm_get_arg_type, firm_emit_ident };
	static lc_arg_handler_t indent_handler = { firm_get_arg_type_int, firm_emit_indent };
	static lc_arg_handler_t pnc_handler    = { firm_get_arg_type_int, firm_emit_pnc };
	static lc_arg_handler_t bitset_handler = { bitset_get_arg_type, bitset_emit };
	static lc_arg_handler_t debug_handler  = { firm_get_arg_type, firm_emit_dbg };
282

Michael Beck's avatar
Michael Beck committed
283
284
285
286
	static struct {
		const char *name;
		char letter;
	} args[] = {
Sebastian Hack's avatar
Sebastian Hack committed
287
#define X(name, letter) {"firm:" name, letter}
Michael Beck's avatar
Michael Beck committed
288
289
290
291
292
293
294
295
296
297
		X("type",      't'),
		X("entity",    'e'),
		X("entity_ld", 'E'),
		X("tarval",    'T'),
		X("irn",       'n'),
		X("op",        'O'),
		X("irn_nr",    'N'),
		X("mode",      'm'),
		X("block",     'B'),
		X("cg_path",   'P'),
Sebastian Hack's avatar
Sebastian Hack committed
298
#undef X
Michael Beck's avatar
Michael Beck committed
299
	};
300

Michael Beck's avatar
Michael Beck committed
301
	size_t i;
302

Michael Beck's avatar
Michael Beck committed
303
304
305
	if (env == NULL) {
		env = lc_arg_new_env();
		lc_arg_add_std(env);
306

Michael Beck's avatar
Michael Beck committed
307
308
309
		lc_arg_register(env, "firm", 'F', &firm_handler);
		for (i = 0; i < sizeof(args)/sizeof(args[0]); ++i)
			lc_arg_register(env, args[i].name, args[i].letter, &firm_handler);
310

Michael Beck's avatar
Michael Beck committed
311
312
313
314
315
316
		lc_arg_register(env, "firm:ident",    'I', &ident_handler);
		lc_arg_register(env, "firm:indent",   'D', &indent_handler);
		lc_arg_register(env, "firm:dbg_info", 'G', &debug_handler);
		lc_arg_register(env, "firm:bitset",   'B', &bitset_handler);
		lc_arg_register(env, "firm:pnc",      '=', &pnc_handler);
	}
317

Michael Beck's avatar
Michael Beck committed
318
	return env;
319
}