irdump.c 86.9 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   Write vcg representation of firm to file.
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt
 * @version $Id$
Götz Lindenmaier's avatar
Götz Lindenmaier committed
25
 */
Michael Beck's avatar
Michael Beck committed
26
#include "config.h"
Christian Schäfer's avatar
Christian Schäfer committed
27

28
29
30
31
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

32
33
#include "list.h"

34
35
#include "irnode_t.h"
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
36
#include "irprog_t.h"
37
#include "entity_t.h"
38
#include "irop.h"
39

40
#include "irdump_t.h"
Michael Beck's avatar
Michael Beck committed
41
#include "irpass_t.h"
42
43
44
45

#include "irgwalk.h"
#include "tv_t.h"
#include "irouts.h"
Michael Beck's avatar
Michael Beck committed
46
#include "iredges.h"
47
#include "irdom.h"
Michael Beck's avatar
Michael Beck committed
48
#include "irloop_t.h"
49
#include "callgraph.h"
50
#include "irextbb_t.h"
51
#include "irhooks.h"
Michael Beck's avatar
Michael Beck committed
52
#include "dbginfo_t.h"
Michael Beck's avatar
Michael Beck committed
53
#include "irtools.h"
54
#include "irprintf.h"
55
56
57

#include "irvrfy.h"

58
#include "error.h"
59
60
61
#include "array.h"
#include "pmap.h"
#include "eset.h"
62
#include "pset.h"
63

64
/** Dump only irgs with names that start with this prefix. */
65
66
static ident *dump_file_filter_id = NULL;

Michael Beck's avatar
Michael Beck committed
67
68
#define ERROR_TXT       "<ERROR>"

69
70
71
72
73
74
75
76
77
/*******************************************************************/
/* flags to steer output                                           */
/*******************************************************************/

/** An option to turn off edge labels */
static int edge_label = 1;
/** An option to turn off dumping values of constant entities */
static int const_entities = 1;
/** An option to dump the keep alive edges */
78
static int dump_keepalive = 1;
Michael Beck's avatar
Michael Beck committed
79
80
/** An option to dump the new out edges */
static int dump_new_edges_flag = 0;
81
82
83
/** An option to dump ld_names instead of names. */
static int dump_ld_name = 1;
/** Compiler options to dump analysis information in dump_ir_graph */
84
85
86
static int dump_out_edge_flag = 0;
static int dump_loop_information_flag = 0;
static int dump_backedge_information_flag = 1;
87
/** An option to dump const-like nodes locally. */
88
static int dump_const_local = 1;
89
/** An option to dump the node index number. */
90
static int dump_node_idx_labels = 0;
91
92
/** An option to dump all graph anchors */
static int dump_anchors = 0;
93
94
/** An option to dump the macro block edges. */
static int dump_macro_block_edges = 0;
95
96
/** An option to dump block marker in the block title */
static int dump_block_marker = 0;
97

98
int dump_dominator_information_flag = 0;
99
100
int opt_dump_analysed_type_info = 1;
int opt_dump_pointer_values_to_info = 0;  /* default off: for test compares!! */
101

102
static ird_color_t overrule_nodecolor = ird_color_default_node;
103

104
105
106
107
108
109
110
111
112
/** The vcg node attribute hook. */
static DUMP_IR_GRAPH_FUNC dump_ir_graph_hook = NULL;
/** The vcg node attribute hook. */
static DUMP_NODE_VCGATTR_FUNC dump_node_vcgattr_hook = NULL;
/** The vcg edge attribute hook. */
static DUMP_EDGE_VCGATTR_FUNC dump_edge_vcgattr_hook = NULL;
/** The vcg dump block edge hook */
static DUMP_NODE_EDGE_FUNC dump_block_edge_hook = NULL;
/** The vcg dump node edge hook. */
113
114
static DUMP_NODE_EDGE_FUNC dump_node_edge_hook = NULL;

115
116
117
/* Set the hook to be called to dump additional edges to a node. */
void set_dump_node_edge_hook(DUMP_NODE_EDGE_FUNC func) {
	dump_node_edge_hook = func;
118
119
}

120
121
122
/* Get the additional edge dump hook. */
DUMP_NODE_EDGE_FUNC get_dump_node_edge_hook(void) {
	return dump_node_edge_hook;
123
124
}

125
126
127
/* Set the hook to be called to dump additional edges to a block. */
void set_dump_block_edge_hook(DUMP_NODE_EDGE_FUNC func) {
	dump_block_edge_hook = func;
128
129
}

130
131
132
/* Get the additional block edge dump hook. */
DUMP_NODE_EDGE_FUNC get_dump_block_edge_hook(void) {
	return dump_node_edge_hook;
133
134
}

135
136
/* set the ir graph hook */
void set_dump_ir_graph_hook(DUMP_IR_GRAPH_FUNC hook) {
137
	dump_ir_graph_hook = hook;
138
}
139

140
/* set the node attribute hook */
141
void set_dump_node_vcgattr_hook(DUMP_NODE_VCGATTR_FUNC hook) {
142
	dump_node_vcgattr_hook = hook;
143
}
144

145
146
/* set the edge attribute hook */
void set_dump_edge_vcgattr_hook(DUMP_EDGE_VCGATTR_FUNC hook) {
147
	dump_edge_vcgattr_hook = hook;
148
}
149

150
/** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
151
152
 * are set, else returns dump_const_local_flag.
 */
153
static int get_opt_dump_const_local(void) {
Michael Beck's avatar
Michael Beck committed
154
	if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
155
		return 0;
Michael Beck's avatar
Michael Beck committed
156
	return dump_const_local;
157
158
}

159
/* Set a prefix filter for output functions. */
160
void only_dump_method_with_name(ident *name) {
161
	dump_file_filter_id = name;
162
163
}

164
/* Returns the prefix filter set with only_dump_method_with_name(). */
165
ident *get_dump_file_filter_ident(void) {
166
	return dump_file_filter_id;
167
168
}

169
/* Returns non-zero if dump file filter is not set, or if it is a prefix of name. */
170
int is_filtered_dump_name(ident *name) {
171
172
	if (!dump_file_filter_id) return 1;
	return id_is_prefix(dump_file_filter_id, name);
173
174
}

Michael Beck's avatar
Michael Beck committed
175
/* To turn off display of edge labels.  Edge labels often cause xvcg to
176
177
   abort with a segmentation fault. */
void turn_off_edge_labels(void) {
178
	edge_label = 0;
179
180
}

181
void dump_consts_local(int flag) {
182
	dump_const_local = flag;
183
184
}

185
186
187
188
void dump_node_idx_label(int flag) {
	dump_node_idx_labels = flag;
}

189
void dump_constant_entity_values(int flag) {
190
	const_entities = flag;
191
192
}

193
void dump_keepalive_edges(int flag) {
194
	dump_keepalive = flag;
195
196
}

Michael Beck's avatar
Michael Beck committed
197
198
199
200
void dump_new_edges(int flag) {
	dump_new_edges_flag = flag;
}

201
int get_opt_dump_keepalive_edges(void) {
202
	return dump_keepalive;
203
204
}

205
void dump_out_edges(int flag) {
206
	dump_out_edge_flag = flag;
207
208
}

209
void dump_dominator_information(int flag) {
210
	dump_dominator_information_flag = flag;
211
212
}

213
void dump_loop_information(int flag) {
214
	dump_loop_information_flag = flag;
215
216
}

217
void dump_backedge_information(int flag) {
218
	dump_backedge_information_flag = flag;
219
220
221
222
223
224
}

/* Dump the information of type field specified in ana/irtypeinfo.h.
 * If the flag is set, the type name is output in [] in the node label,
 * else it is output as info.
 */
225
void set_opt_dump_analysed_type_info(int flag) {
226
	opt_dump_analysed_type_info = flag;
227
228
}

229
void dump_pointer_values_to_info(int flag) {
230
	opt_dump_pointer_values_to_info = flag;
231
232
}

233
void dump_ld_names(int flag) {
234
	dump_ld_name = flag;
235
236
}

237
void dump_all_anchors(int flag) {
238
	dump_anchors = flag;
239
240
}

241
242
243
244
void dump_macroblock_edges(int flag) {
	dump_macro_block_edges = flag;
}

245
246
247
248
void dump_block_marker_in_title(int flag) {
	dump_block_marker = flag;
}

249
250
/* -------------- some extended helper functions ----------------- */

Michael Beck's avatar
Michael Beck committed
251
/**
252
253
 * returns the name of a mode or ERROR_TXT if mode is NOT a mode object.
 * in the later case, sets bad.
Michael Beck's avatar
Michael Beck committed
254
 */
Michael Beck's avatar
Michael Beck committed
255
const char *get_mode_name_ex(const ir_mode *mode, int *bad) {
256
257
258
259
	if (is_mode(mode))
		return get_mode_name(mode);
	*bad |= 1;
	return ERROR_TXT;
260
261
}

262
263
264
265
266
#define CUSTOM_COLOR_BASE    100
static const char *color_names[ird_color_count];
static const char *color_rgb[ird_color_count];
static struct obstack color_obst;

Michael Beck's avatar
Michael Beck committed
267
/** define a custom color. */
268
269
270
271
272
273
274
275
276
277
static void custom_color(int num, const char *rgb_def)
{
	assert(num < ird_color_count);
	obstack_printf(&color_obst, "%d", CUSTOM_COLOR_BASE + num);
	obstack_1grow(&color_obst, '\0');

	color_rgb[num]   = rgb_def;
	color_names[num] = obstack_finish(&color_obst);
}

Michael Beck's avatar
Michael Beck committed
278
/** Define a named color. */
279
280
281
282
283
284
285
static void named_color(int num, const char *name)
{
	assert(num < ird_color_count);
	color_rgb[num]   = NULL;
	color_names[num] = name;
}

Michael Beck's avatar
Michael Beck committed
286
/** Initializes the used colors. */
287
288
289
static void init_colors(void)
{
	static int initialized = 0;
Michael Beck's avatar
Michael Beck committed
290
	if (initialized)
291
292
293
294
295
296
297
298
299
300
301
302
303
		return;

	obstack_init(&color_obst);

	custom_color(ird_color_prog_background,       "204 204 204");
	custom_color(ird_color_block_background,      "255 255 0");
	custom_color(ird_color_dead_block_background, "190 150 150");
	named_color(ird_color_block_inout,            "lightblue");
	named_color(ird_color_default_node,           "white");
	custom_color(ird_color_memory,                "153 153 255");
	custom_color(ird_color_controlflow,           "255 153 153");
	custom_color(ird_color_const,                 "204 255 255");
	custom_color(ird_color_proj,                  "255 255 153");
304
	custom_color(ird_color_uses_memory,           "153 153 255");
305
306
307
	custom_color(ird_color_phi,                   "105 255 105");
	custom_color(ird_color_anchor,                "100 100 255");
	named_color(ird_color_error,                  "red");
308
	custom_color(ird_color_entity,                "204 204 255");
309
310
311
312

	initialized = 1;
}

313
/**
314
 * Prints the VCG color to a file.
315
 */
316
317
318
static void print_vcg_color(FILE *F, ird_color_t color) {
	assert(color < ird_color_count);
	fprintf(F, "color:%s", color_names[color]);
319
320
}

321
322
323
324
325
326
327
328
329
330
331
332
333
/**
 * Prints the edge kind of a given IR node.
 *
 * Projs should be dumped near their predecessor, so they get "nearedge".
 */
static void print_node_edge_kind(FILE *F, ir_node *node) {
	if (is_Proj(node)) {
		fprintf(F, "nearedge: ");
	} else {
		fprintf(F, "edge: ");
	}
}

Michael Beck's avatar
Michael Beck committed
334
/**
335
336
 * Prints the edge from a type S to a type T with additional info fmt, ...
 * to the file F.
Michael Beck's avatar
Michael Beck committed
337
 */
Michael Beck's avatar
Michael Beck committed
338
static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
339
{
340
	va_list ap;
341

342
343
344
345
346
347
	va_start(ap, fmt);
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
	fprintf(F, " targetname: "); PRINT_TYPEID(T);
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
348
349
}

Michael Beck's avatar
Michael Beck committed
350
/**
Michael Beck's avatar
Michael Beck committed
351
 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
352
 * to the file F.
Michael Beck's avatar
Michael Beck committed
353
 */
Michael Beck's avatar
Michael Beck committed
354
static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
355
{
356
	va_list ap;
357

358
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
359
360
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
	fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
361
362
363
	vfprintf(F, fmt, ap);
	fprintf(F, "}\n");
	va_end(ap);
364
365
}

Michael Beck's avatar
Michael Beck committed
366
/**
Michael Beck's avatar
Michael Beck committed
367
 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
368
 * to the file F.
Michael Beck's avatar
Michael Beck committed
369
 */
Michael Beck's avatar
Michael Beck committed
370
static void print_ent_ent_edge(FILE *F, const ir_entity *ent1, const ir_entity *ent2, int backedge, ird_color_t color, const char *fmt, ...)
371
{
372
	va_list ap;
373

374
375
376
377
378
	va_start(ap, fmt);
	if (backedge)
		fprintf(F, "backedge: { sourcename: \"");
	else
		fprintf(F, "edge: { sourcename: \"");
Michael Beck's avatar
Michael Beck committed
379
380
	PRINT_ENTID(ent1);
	fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2);  fprintf(F, "\"");
381
	vfprintf(F, fmt, ap);
382
383
384
	fprintf(F, " ");
	if (color != (ird_color_t) -1)
		print_vcg_color(F, color);
385
386
	fprintf(F, "}\n");
	va_end(ap);
387
388
}

Michael Beck's avatar
Michael Beck committed
389
/**
Michael Beck's avatar
Michael Beck committed
390
 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
391
 * to the file F.
Michael Beck's avatar
Michael Beck committed
392
 */
Michael Beck's avatar
Michael Beck committed
393
static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
394
{
395
	va_list ap;
396

397
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
398
399
	fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
	fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
400
401
402
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
403
404
}

Michael Beck's avatar
Michael Beck committed
405
/**
Michael Beck's avatar
Michael Beck committed
406
 * Prints the edge from a node irn to a type tp with additional info fmt, ...
407
 * to the file F.
Michael Beck's avatar
Michael Beck committed
408
 */
Michael Beck's avatar
Michael Beck committed
409
static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
410
{
411
	va_list ap;
412

413
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
414
415
	fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
	fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
416
417
418
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
419
420
}

Michael Beck's avatar
Michael Beck committed
421
/**
Michael Beck's avatar
Michael Beck committed
422
 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
423
 * to the file F.
Michael Beck's avatar
Michael Beck committed
424
 */
Michael Beck's avatar
Michael Beck committed
425
static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
426
{
427
	va_list ap;
428

429
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
430
431
	fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
	fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
432
433
434
435
	fprintf(F, "\"");
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
436
437
}

Michael Beck's avatar
Michael Beck committed
438
/**
Michael Beck's avatar
Michael Beck committed
439
 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
440
 * to the file F.
Michael Beck's avatar
Michael Beck committed
441
 */
Michael Beck's avatar
Michael Beck committed
442
static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
443
{
444
	va_list ap;
445

446
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
447
448
	fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
	fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
449
450
451
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
452
}
453

Michael Beck's avatar
Michael Beck committed
454
/**
Michael Beck's avatar
Michael Beck committed
455
 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
456
 * to the file F.
Michael Beck's avatar
Michael Beck committed
457
 */
Michael Beck's avatar
Michael Beck committed
458
static void print_enum_item_edge(FILE *F, const ir_type *tp, int item, const char *fmt, ...)
459
{
460
	va_list ap;
461

462
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
463
464
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
	fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
465
466
467
	vfprintf(F, fmt, ap);
	fprintf(F,"}\n");
	va_end(ap);
468
469
}

Michael Beck's avatar
Michael Beck committed
470
/*-----------------------------------------------------------------*/
471
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
472
/*-----------------------------------------------------------------*/
473

474
static void dump_whole_node(ir_node *n, void *env);
475
static inline void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
476

Michael Beck's avatar
Michael Beck committed
477
/*-----------------------------------------------------------------*/
478
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
479
/*-----------------------------------------------------------------*/
480

Michael Beck's avatar
Michael Beck committed
481
482
483
484
/**
 * This map is used as a private link attr to be able to call dumper
 * anywhere without destroying link fields.
 */
485
486
static pmap *irdump_link_map = NULL;

487
488
489
490
/** NOT A STANDARD LIBFIRM INIT METHOD
 *
 * We do not want to integrate dumping into libfirm, i.e., if the dumpers
 * are off, we want to have as few interferences as possible.  Therefore the
Michael Beck's avatar
Michael Beck committed
491
 * initialization is performed lazily and not called from within init_firm.
492
 *
Michael Beck's avatar
Michael Beck committed
493
 * Creates the link attribute map. */
494
static void init_irdump(void) {
495
496
497
498
499
	/* We need a new, empty map. */
	if (irdump_link_map) pmap_destroy(irdump_link_map);
	irdump_link_map = pmap_create();
	if (!dump_file_filter_id)
		dump_file_filter_id = new_id_from_str("");
500
}
501

Michael Beck's avatar
Michael Beck committed
502
503
504
/**
 * Returns the private link field.
 */
Michael Beck's avatar
Michael Beck committed
505
static void *ird_get_irn_link(const ir_node *n) {
506
	void *res = NULL;
Michael Beck's avatar
Michael Beck committed
507
508
	if (irdump_link_map == NULL)
		return NULL;
509

Michael Beck's avatar
Michael Beck committed
510
511
	if (pmap_contains(irdump_link_map, n))
		res = pmap_get(irdump_link_map, n);
512
	return res;
513
514
}

Michael Beck's avatar
Michael Beck committed
515
516
517
/**
 * Sets the private link field.
 */
Michael Beck's avatar
Michael Beck committed
518
519
static void ird_set_irn_link(const ir_node *n, void *x) {
	if (irdump_link_map == NULL)
520
		init_irdump();
Michael Beck's avatar
Michael Beck committed
521
	pmap_insert(irdump_link_map, n, x);
522
523
}

Michael Beck's avatar
Michael Beck committed
524
525
526
/**
 * Gets the private link field of an irg.
 */
Michael Beck's avatar
Michael Beck committed
527
static void *ird_get_irg_link(const ir_graph *irg) {
528
	void *res = NULL;
Michael Beck's avatar
Michael Beck committed
529
530
	if (irdump_link_map == NULL)
		return NULL;
531

Michael Beck's avatar
Michael Beck committed
532
533
	if (pmap_contains(irdump_link_map, irg))
		res = pmap_get(irdump_link_map, irg);
534
	return res;
535
536
}

Michael Beck's avatar
Michael Beck committed
537
538
539
/**
 * Sets the private link field of an irg.
 */
Michael Beck's avatar
Michael Beck committed
540
541
542
543
static void ird_set_irg_link(const ir_graph *irg, void *x) {
	if (irdump_link_map == NULL)
		init_irdump();
	pmap_insert(irdump_link_map, irg, x);
544
545
}

Michael Beck's avatar
Michael Beck committed
546
/**
547
 * Walker, clears the private link field.
Michael Beck's avatar
Michael Beck committed
548
 */
Michael Beck's avatar
Michael Beck committed
549
static void clear_link(ir_node *node, void *env) {
550
	(void) env;
551
	ird_set_irn_link(node, NULL);
552
553
}

Michael Beck's avatar
Michael Beck committed
554
/**
555
 * If the entity has a ld_name, returns it if the dump_ld_name is set,
556
 * else returns the name of the entity.
Michael Beck's avatar
Michael Beck committed
557
 */
Michael Beck's avatar
Michael Beck committed
558
559
static const char *_get_ent_dump_name(const ir_entity *ent, int dump_ld_name) {
	if (ent == NULL)
560
561
562
		return "<NULL entity>";
	if (dump_ld_name) {
		/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
Michael Beck's avatar
Michael Beck committed
563
564
		if (ent->ld_name != NULL)
			return get_id_str(ent->ld_name);
565
566
	}
	return get_id_str(ent->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
567
568
}

569
570
571
572
/**
 * If the entity has a ld_name, returns it if the option dump_ld_name is set,
 * else returns the name of the entity.
 */
Michael Beck's avatar
Michael Beck committed
573
const char *get_ent_dump_name(const ir_entity *ent) {
574
	return _get_ent_dump_name(ent, dump_ld_name);
575
576
}

Michael Beck's avatar
Michael Beck committed
577
/* Returns the name of an IRG. */
Michael Beck's avatar
Michael Beck committed
578
const char *get_irg_dump_name(const ir_graph *irg) {
579
580
	/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
	return _get_ent_dump_name(get_irg_entity(irg), 1);
581
582
}

583
584
585
/**
 * Returns non-zero if a node is in floating state.
 */
Michael Beck's avatar
Michael Beck committed
586
static int node_floats(const ir_node *n) {
587
588
	return ((get_irn_pinned(n) == op_pin_state_floats) &&
	        (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
589
590
}

591
592
593
594
/**
 *  Walker that visits the anchors
 */
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
Michael Beck's avatar
Michael Beck committed
595
	if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
Michael Beck's avatar
Michael Beck committed
596
		irg_walk_anchors(irg, pre, post, env);
597
598
	} else {
		irg_walk_graph(irg, pre, post, env);
599
	}
600
601
}

Michael Beck's avatar
Michael Beck committed
602
603
604
/**
 * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
 */
Michael Beck's avatar
Michael Beck committed
605
static void collect_node(ir_node *node, void *env) {
606
	(void) env;
607
608
	if (is_Block(node)
	    || node_floats(node)
609
	    || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
		ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
		if (!arr) arr = NEW_ARR_F(ir_node *, 0);
		ARR_APP1(ir_node *, arr, node);
		ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
	} else {
		ir_node * block = get_nodes_block(node);

		if (is_Bad(block)) {
			/* this node is in a Bad block, so we must place it into the graph's list */
			ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
			if (!arr) arr = NEW_ARR_F(ir_node *, 0);
			ARR_APP1(ir_node *, arr, node);
			ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
		} else {
			ird_set_irn_link(node, ird_get_irn_link(block));
			ird_set_irn_link(block, node);
		}
	}
628
629
630
631
}

/** Construct lists to walk ir block-wise.
 *
632
 * Collects all blocks, nodes not op_pin_state_pinned,
633
 * Bad, NoMem and Unknown into a flexible array in link field of
634
635
 * irg they belong to.  Sets the irg link field to NULL in all
 * graphs not visited.
Michael Beck's avatar
Michael Beck committed
636
637
 * Free the list with DEL_ARR_F().
 */
638
static ir_node **construct_block_lists(ir_graph *irg) {
639
	int      i;
640
#ifdef INTERPROCEDURAL_VIEW
641
	int      rem_view  = get_interprocedural_view();
642
#endif
643
	int      walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
644
645
	ir_graph *rem      = current_ir_graph;

646
	current_ir_graph = irg;
647

Matthias Braun's avatar
Matthias Braun committed
648
	if(walk_flag) {
649
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
650
	}
651

652
653
	for (i = get_irp_n_irgs() - 1; i >= 0; --i)
		ird_set_irg_link(get_irp_irg(i), NULL);
654

655
	ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
656

657
#ifdef INTERPROCEDURAL_VIEW
658
659
	/* Collect also EndReg and EndExcept. We do not want to change the walker. */
	set_interprocedural_view(0);
660
#endif
661

662
663
664
665
	set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
	irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
	set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
	irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
666

667
#ifdef INTERPROCEDURAL_VIEW
668
	set_interprocedural_view(rem_view);
669
#endif
670

Michael Beck's avatar
Michael Beck committed
671
	if (walk_flag) {
672
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
673
	}
674

675
676
	current_ir_graph = rem;
	return ird_get_irg_link(irg);
677
678
}

679
typedef struct _list_tuple {
680
681
	ir_node **blk_list;
	ir_extblk **extbb_list;
682
683
} list_tuple;

684
/** Construct lists to walk IR extended block-wise.
685
 * Free the lists in the tuple with DEL_ARR_F().
686
687
 * Sets the irg link field to NULL in all
 * graphs not visited.
688
689
 */
static list_tuple *construct_extblock_lists(ir_graph *irg) {
690
691
692
	ir_node **blk_list = construct_block_lists(irg);
	int i;
	ir_graph *rem = current_ir_graph;
693
	list_tuple *lists = XMALLOC(list_tuple);
694

695
	current_ir_graph = irg;
696

697
698
	lists->blk_list   = NEW_ARR_F(ir_node *, 0);
	lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
699

700
701
702
	inc_irg_block_visited(irg);
	for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
		ir_extblk *ext;
703

704
705
		if (is_Block(blk_list[i])) {
			ext = get_Block_extbb(blk_list[i]);
706

707
708
709
710
711
712
713
714
			if (extbb_not_visited(ext)) {
				ARR_APP1(ir_extblk *, lists->extbb_list, ext);
				mark_extbb_visited(ext);
			}
		} else
			ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
	}
	DEL_ARR_F(blk_list);
715

716
717
718
	current_ir_graph = rem;
	ird_set_irg_link(irg, lists);
	return lists;
719
720
}

721
/*-----------------------------------------------------------------*/
722
/* Routines to dump information about a single ir node.            */
723
/*-----------------------------------------------------------------*/
724

725
/*
Michael Beck's avatar
Michael Beck committed
726
727
 * dump the name of a node n to the File F.
 */
728
int dump_node_opcode(FILE *F, ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
729
{
730
731
732
733
734
735
736
737
738
	int bad = 0;
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
	if (ops->dump_node)
		return ops->dump_node(n, F, dump_node_opcode_txt);

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
739
	case iro_SymConst:
740
741
742
743
744
745
746
747
748
749
750
751
		switch (get_SymConst_kind(n)) {
		case symconst_addr_name:
			/* don't use get_SymConst_ptr_info as it mangles the name. */
			fprintf(F, "SymC %s", get_id_str(get_SymConst_name(n)));
			break;
		case symconst_addr_ent:
			fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
			break;
		case symconst_ofs_ent:
			fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
			break;
		case symconst_type_tag:
752
			ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
753
754
			break;
		case symconst_type_size:
755
			ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
756
757
			break;
		case symconst_type_align:
758
			ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
759
760
			break;
		case symconst_enum_const:
761
			fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
762
763
			break;
		}
764
		break;
765

766
	case iro_Filter:
767
768
769
770
		if (!get_interprocedural_view())
			fprintf(F, "Proj'");
		else
			goto default_case;
771
		break;
772
773
774
775
776

	case iro_Proj: {
		ir_node *pred = get_Proj_pred(n);

		if (get_irn_opcode(pred) == iro_Cond
777
			&& get_Proj_proj(n) == get_Cond_default_proj(pred)
778
779
780
781
782
783
784
785
			&& get_irn_mode(get_Cond_selector(pred)) != mode_b)
			fprintf(F, "defProj");
		else
			goto default_case;
	} break;
	case iro_Start:
	case iro_End:
	case iro_EndExcept:
786
	case iro_EndReg:
787
788
789
790
791
		if (get_interprocedural_view()) {
			fprintf(F, "%s %s", get_irn_opname(n), get_ent_dump_name(get_irg_entity(get_irn_irg(n))));
			break;
		} else
			goto default_case;
792

793
794
795
	case iro_CallBegin: {
		ir_node *addr = get_CallBegin_ptr(n);
		ir_entity *ent = NULL;
796
		if (is_Sel(addr))
797
			ent = get_Sel_entity(addr);
798
799
		else if (is_Global(addr))
			ent = get_Global_entity(addr);
800
801
802
803
804
		fprintf(F, "%s", get_irn_opname(n));
		if (ent) fprintf(F, " %s", get_entity_name(ent));
		break;
	}
	case iro_Load:
Michael Beck's avatar
Michael Beck committed
805
806
		if (get_Load_align(n) == align_non_aligned)
			fprintf(F, "ua");
807
808
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
		break;
Michael Beck's avatar
Michael Beck committed
809
810
811
812
813
	case iro_Store:
		if (get_Store_align(n) == align_non_aligned)
			fprintf(F, "ua");
		fprintf(F, "%s", get_irn_opname(n));
		break;
814
	case iro_Block:
815
816
817
		fprintf(F, "%s%s%s",
			is_Block_dead(n) ? "Dead " : "", get_irn_opname(n),
			dump_block_marker ? (get_Block_mark(n) ? "*" : "") : "");
818
819
820
821
822
823
		break;
	case iro_Conv:
		if (get_Conv_strict(n))
			fprintf(F, "strict");
		fprintf(F, "%s", get_irn_opname(n));
		break;
824
	case iro_Div:
825
		fprintf(F, "%s", get_irn_opname(n));
826
		if (get_Div_no_remainder(n))
827
828
			fprintf(F, "RL");
		fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), &bad));
829
830
831
832
833
834
835
		break;
	case iro_Mod:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
		break;
	case iro_DivMod:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
		break;
836
837
838
	case iro_Builtin:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
		break;
839
840

	default:
841
default_case:
842
		fprintf(F, "%s", get_irn_opname(n));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
843

844
845
	}  /* end switch */
	return bad;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
846
847
}

Michael Beck's avatar
Michael Beck committed
848
849
850
851
/**
 * Dump the mode of a node n to a file F.
 * Ignore modes that are "always known".
 */
852
static int dump_node_mode(FILE *F, ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
853
{
Michael Beck's avatar
Michael Beck committed
854
	int             bad = 0;
855
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
Michael Beck's avatar
Michael Beck committed
856
857
	ir_opcode       iro;
	ir_mode         *mode;
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874

	/* call the dump_node operation if available */
	if (ops->dump_node)
		return ops->dump_node(n, F, dump_node_mode_txt);

	/* default implementation */
	iro = get_irn_opcode(n);
	switch (iro) {
	case iro_SymConst:
	case iro_Sel:
	case iro_End:
	case iro_Return:
	case iro_Free:
	case iro_Sync:
	case iro_Jmp:
	case iro_NoMem:
		break;
Michael Beck's avatar
Michael Beck committed
875
876
	default: