irargs.c 8.15 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
/**
 * @file
 * @brief    Support for libcore IR object output.
 * @author   Sebastian Hack
10
 */
11
#include "irargs_t.h"
12

13
14
#include <ctype.h>

15
#include "bitset.h"
Matthias Braun's avatar
Matthias Braun committed
16
#include "lc_printf.h"
17
#include "firm_common.h"
18
19
20
21
#include "irnode_t.h"
#include "entity_t.h"
#include "irloop_t.h"
#include "tv_t.h"
22
#include "dbginfo_t.h"
23
#include "util.h"
24
25
26
27

/**
 * identify a firm object type
 */
28
29
static int firm_get_arg_type(const lc_arg_occ_t *occ)
{
Michael Beck's avatar
Michael Beck committed
30
31
32
	(void) occ;
	/* Firm objects are always pointer */
	return lc_arg_type_ptr;
33
34
}

35
36
static int firm_get_arg_type_int(const lc_arg_occ_t *occ)
{
Michael Beck's avatar
Michael Beck committed
37
38
	(void) occ;
	return lc_arg_type_int;
39
40
}

41

42
43
static int bitset_get_arg_type(const lc_arg_occ_t *occ)
{
Michael Beck's avatar
Michael Beck committed
44
45
	(void) occ;
	return lc_arg_type_ptr;
46
47
}

Sebastian Hack's avatar
Sebastian Hack committed
48
49
static int bitset_emit(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
50
{
51
	bitset_t *b = (bitset_t*)arg->v_ptr;
Michael Beck's avatar
Michael Beck committed
52
53
54
	char buf[32];
	const char *prefix = "";

55
	int res = 0;
Michael Beck's avatar
Michael Beck committed
56
	lc_arg_append(app, occ, "[", 1);
57
	++res;
Michael Beck's avatar
Michael Beck committed
58
59
60
61
62
63
64
65
66
	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);
67
	++res;
Michael Beck's avatar
Michael Beck committed
68
69

	return res;
70
71
}

72
73
74
/**
 * emit an opaque Firm dbg_info object
 */
Sebastian Hack's avatar
Sebastian Hack committed
75
76
static int firm_emit_dbg(lc_appendable_t *app,
    const lc_arg_occ_t *occ, const lc_arg_value_t *arg)
77
{
Michael Beck's avatar
Michael Beck committed
78
	char buf[1024];
79
	ir_node *irn = (ir_node*)arg->v_ptr;
Michael Beck's avatar
Michael Beck committed
80
81
	dbg_info *dbg = get_irn_dbg_info(irn);

82
	ir_dbg_info_snprint(buf, sizeof(buf), dbg);
83
84
85
	size_t size = strlen(buf);
	lc_arg_append(app, occ, buf, size);
	return size;
86
87
}

88
89
90
/**
 * Beware: do not set the entity ld_name
 */
91
92
static const char *get_entity_ld_name_ex(ir_entity *ent)
{
Michael Beck's avatar
Michael Beck committed
93
94
95
	if (ent->ld_name)
		return get_entity_ld_name(ent);
	return get_entity_name(ent);
96
97
}

98
99
100
/**
 * emit a Firm object
 */
101
102
static int firm_emit(lc_appendable_t *app, const lc_arg_occ_t *occ,
                     const lc_arg_value_t *arg)
103
{
104
#define A(s)    occ->flag_hash ? s " ": ""
105

106
107
	void *X = (void*)arg->v_ptr;
	firm_kind *obj = (firm_kind*)X;
Michael Beck's avatar
Michael Beck committed
108
109
110
111
112
113
114
115
	ir_node *block;
	char add[64];
	char buf[256];
	char tv_buf[256];

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

116
117
118
119
120
	if (X == NULL) {
		return lc_arg_append(app, occ, "(null)", 6);
	}

	switch (*obj) {
Michael Beck's avatar
Michael Beck committed
121
122
123
124
	case k_BAD:
		snprintf(buf, sizeof(buf), "BAD");
		snprintf(add, sizeof(add), "[%p]", X);
		break;
125
126
	case k_entity: {
		ir_entity *entity = (ir_entity*)X;
Michael Beck's avatar
Michael Beck committed
127
		snprintf(buf, sizeof(buf), "%s%s", A("ent"),
128
			isupper((unsigned char)occ->conversion) ? get_entity_ld_name_ex(entity): get_entity_name(entity));
129
		snprintf(add, sizeof(add), "[%ld]", get_entity_nr(entity));
Michael Beck's avatar
Michael Beck committed
130
		break;
131
	}
132
	case k_type: {
133
		ir_type *type = (ir_type*)X;
134
		char type_name[256];
135
136
137
138
		ir_print_type(type_name, sizeof(type_name), type);
		snprintf(buf, sizeof(buf), "%s%s:%s", A("type"),
		         get_type_tpop_name(type), type_name);
		snprintf(add, sizeof(add), "[%ld]", get_type_nr(type));
Michael Beck's avatar
Michael Beck committed
139
		break;
140
	}
141
142
143
	case k_ir_graph: {
		ir_graph *irg = (ir_graph*)X;
		if (irg == get_const_code_irg())
Michael Beck's avatar
Michael Beck committed
144
145
			snprintf(buf, sizeof(buf), "%s<ConstCodeIrg>", A("irg"));
		else
146
147
			snprintf(buf, sizeof(buf), "%s%s", A("irg"), get_entity_name(get_irg_entity(irg)));
		snprintf(add, sizeof(add), "[%ld]", get_irg_graph_nr(irg));
Michael Beck's avatar
Michael Beck committed
148
		break;
149
150
151
	}
	case k_ir_node: {
		ir_node *node = (ir_node*)X;
Michael Beck's avatar
Michael Beck committed
152
153
		switch (occ->conversion) {
		case 'B':
154
			block = !is_Block(node) ? get_nodes_block(node) : node;
155
156
			snprintf(buf, sizeof(buf), "%s%s %s", A("irn"),
			         get_irn_opname(block), get_mode_name(get_irn_mode(block)));
Michael Beck's avatar
Michael Beck committed
157
158
159
			snprintf(add, sizeof(add), "[%ld]", get_irn_node_nr(block));
			break;
		case 'N':
160
			snprintf(buf, sizeof(buf), "%ld", get_irn_node_nr(node));
Michael Beck's avatar
Michael Beck committed
161
162
			break;
		default:
163
164
			if (is_Const(node)) {
				ir_tarval *tv = get_Const_tarval(node);
Michael Beck's avatar
Michael Beck committed
165
				if (tv)
166
167
					tarval_snprintf(tv_buf, sizeof(tv_buf), tv,
					                !mode_is_float(get_tarval_mode(tv)));
Michael Beck's avatar
Michael Beck committed
168
169
				else
					strncpy(tv_buf, "(NULL)", sizeof(tv_buf));
170
171
172
173
174
175
				snprintf(buf, sizeof(buf), "%s%s %s<%s>", A("irn"), get_irn_opname(node),
					get_mode_name(get_irn_mode(node)), tv_buf);
			} else if (is_SymConst_addr_ent(node)) {
				snprintf(buf, sizeof(buf), "%s%s %s[%s]", A("irn"), get_irn_opname(node),
				get_mode_name(get_irn_mode(node)), get_entity_name(get_SymConst_entity(node)));
			} else if (is_Sel(node)) {
176
177
178
179
				ir_entity *entity = get_Sel_entity(node);
				const char *entity_name = "(null)";
				if (entity != NULL)
					entity_name = get_entity_name(entity);
180
				snprintf(buf, sizeof(buf), "%s%s %s[%s]", A("irn"), get_irn_opname(node),
181
				get_mode_name(get_irn_mode(node)), entity_name);
182
183
184
			} else if (is_Cmp(node)) {
				ir_relation relation = get_Cmp_relation(node);
				snprintf(buf, sizeof(buf), "%s%s %s", A("irn"), get_irn_opname(node), get_relation_string(relation));
185
			} else {
186
187
				snprintf(buf, sizeof(buf), "%s%s %s", A("irn"), get_irn_opname(node),
				get_mode_name(get_irn_mode(node)));
Michael Beck's avatar
Michael Beck committed
188
			}
189
			snprintf(add, sizeof(add), "[%ld:%u]", get_irn_node_nr(node), get_irn_idx(node));
190
191
		}
		break;
192
193
194
195
	}
	case k_ir_mode: {
		ir_mode *mode = (ir_mode*)X;
		snprintf(buf, sizeof(buf), "%s%s", A("mode"), get_mode_name(mode));
Michael Beck's avatar
Michael Beck committed
196
		break;
197
198
199
	}
	case k_tarval: {
		ir_tarval *tarval = (ir_tarval*)X;
200
201
		tarval_snprintf(tv_buf, sizeof(tv_buf), tarval,
		                !mode_is_float(get_tarval_mode(tarval)));
Michael Beck's avatar
Michael Beck committed
202
203
		snprintf(buf, sizeof(buf), "%s%s", A("tv"), tv_buf);
		break;
204
205
206
	}
	case k_ir_loop: {
		ir_loop *loop = (ir_loop*)X;
Matthias Braun's avatar
Matthias Braun committed
207
		snprintf(buf, sizeof(buf), "loop[%ld:%u]", get_loop_loop_nr(loop), get_loop_depth(loop));
Michael Beck's avatar
Michael Beck committed
208
		break;
209
210
211
212
	}
	case k_ir_op: {
		ir_op *op = (ir_op*)X;
		snprintf(buf, sizeof(buf), "%s%s", A("op"), get_op_name(op));
Michael Beck's avatar
Michael Beck committed
213
		break;
214
	}
Michael Beck's avatar
Michael Beck committed
215
216
217
218
219
220
221

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

	if (occ->flag_plus)
222
		strncat(buf, add, sizeof(buf)-strlen(buf)-1);
Michael Beck's avatar
Michael Beck committed
223

224
225
226
	size_t size = strlen(buf);
	lc_arg_append(app, occ, buf, size);
	return size;
227
228
229
230
231
232
#undef A
}

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

239
240
241
	size_t size = strlen(p);
	lc_arg_append(app, occ, p, size);
	return size;
242
243
}

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

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

	return amount;
}

260
261
262
/**
 * Emit pnc.
 */
263
264
static int firm_emit_pnc(lc_appendable_t *app, const lc_arg_occ_t *occ,
                         const lc_arg_value_t *arg)
265
{
266
	ir_relation value = (ir_relation)arg->v_int;
267
	const char *p = get_relation_string(value);
268

269
270
271
	size_t size = strlen(p);
	lc_arg_append(app, occ, p, size);
	return size;
272
273
}

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

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

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

Michael Beck's avatar
Michael Beck committed
286
287
288
289
	static struct {
		const char *name;
		char letter;
	} args[] = {
290
291
292
293
294
295
296
297
298
		{"firm:type",      't'},
		{"firm:entity",    'e'},
		{"firm:entity_ld", 'E'},
		{"firm:tarval",    'T'},
		{"firm:irn",       'n'},
		{"firm:op",        'O'},
		{"firm:irn_nr",    'N'},
		{"firm:mode",      'm'},
		{"firm:block",     'B'},
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
		lc_arg_register(env, "firm", 'F', &firm_handler);
308
		for (i = 0; i != ARRAY_SIZE(args); ++i)
Michael Beck's avatar
Michael Beck committed
309
			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
}