irargs.c 7.98 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

Matthias Braun's avatar
Matthias Braun committed
30
31
#include "firm_config.h"

32
33
#include "bitset.h"

34
35
#include <ctype.h>

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

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

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

58

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

Sebastian Hack's avatar
Sebastian Hack committed
64
65
static int bitset_emit(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
66
{
Michael Beck's avatar
Michael Beck committed
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	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;
85
86
}

87
88
89
/**
 * emit an opaque Firm dbg_info object
 */
Sebastian Hack's avatar
Sebastian Hack committed
90
91
static int firm_emit_dbg(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
92
{
Michael Beck's avatar
Michael Beck committed
93
94
95
96
97
98
99
100
101
102
	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));
103
104
}

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

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

Michael Beck's avatar
Michael Beck committed
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
227
228
	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));
229
230
231
232
233
234
235

#undef A
}

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

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

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

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

	return amount;
}

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

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

Sebastian Hack's avatar
Sebastian Hack committed
273
lc_arg_env_t *firm_get_arg_env(void)
274
275
{

Michael Beck's avatar
Michael Beck committed
276
	static lc_arg_env_t *env = NULL;
277

Michael Beck's avatar
Michael Beck committed
278
279
280
281
282
283
	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 };
284

Michael Beck's avatar
Michael Beck committed
285
286
287
288
	static struct {
		const char *name;
		char letter;
	} args[] = {
Sebastian Hack's avatar
Sebastian Hack committed
289
#define X(name, letter) {"firm:" name, letter}
Michael Beck's avatar
Michael Beck committed
290
291
292
293
294
295
296
297
298
299
		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
300
#undef X
Michael Beck's avatar
Michael Beck committed
301
	};
302

Michael Beck's avatar
Michael Beck committed
303
	size_t i;
304

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

Michael Beck's avatar
Michael Beck committed
309
310
311
		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);
312

Michael Beck's avatar
Michael Beck committed
313
314
315
316
317
318
		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);
	}
319

Michael Beck's avatar
Michael Beck committed
320
	return env;
321
}