irdump.c 71.5 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
2
 * Copyright (C) 1995-2011 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
/**
 * @file
 * @brief   Write vcg representation of firm to file.
23
24
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt,
 *          Matthias Braun
Matthias Braun's avatar
Matthias Braun committed
25
 * @version $Id$
Götz Lindenmaier's avatar
Götz Lindenmaier committed
26
 */
Michael Beck's avatar
Michael Beck committed
27
#include "config.h"
Christian Schäfer's avatar
Christian Schäfer committed
28

29
30
31
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
32
33
#include <stdbool.h>
#include <errno.h>
34

35
36
#include "list.h"

37
38
#include "irnode_t.h"
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
39
#include "irprog_t.h"
40
#include "entity_t.h"
41
#include "irop.h"
42

43
#include "irdump_t.h"
Michael Beck's avatar
Michael Beck committed
44
#include "irpass_t.h"
45
46
47
48

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

59
#include "irverify.h"
60

61
#include "error.h"
62
63
#include "array.h"
#include "pmap.h"
64
#include "obst.h"
65
#include "eset.h"
66
#include "pset.h"
67
#include "util.h"
68

69
/** Dump only irgs with names that start with this prefix. */
70
71
static ident *dump_file_filter_id = NULL;

72
73
74
75
76
77
78
static ir_dump_flags_t flags =
	ir_dump_flag_blocks_as_subgraphs |
	ir_dump_flag_keepalive_edges |
	ir_dump_flag_ld_names |
	ir_dump_flag_back_edges |
	ir_dump_flag_consts_local |
	ir_dump_flag_analysed_types |
Matthias Braun's avatar
Matthias Braun committed
79
80
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
81

82
static ird_color_t overrule_nodecolor = ird_color_default_node;
83

84
/** The vcg node attribute hook. */
85
static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
86
/** The vcg edge attribute hook. */
87
static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
88
/** The vcg dump block edge hook */
89
static dump_node_edge_func dump_block_edge_hook = NULL;
90
/** The vcg dump node edge hook. */
91
static dump_node_edge_func dump_node_edge_hook = NULL;
92

93
void set_dump_node_edge_hook(dump_node_edge_func func)
94
{
95
	dump_node_edge_hook = func;
96
97
}

98
dump_node_edge_func get_dump_node_edge_hook(void)
99
{
100
	return dump_node_edge_hook;
101
102
}

103
void set_dump_block_edge_hook(dump_node_edge_func func)
104
{
105
	dump_block_edge_hook = func;
106
107
}

108
dump_node_edge_func get_dump_block_edge_hook(void)
109
{
110
	return dump_node_edge_hook;
111
112
}

113
void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
114
{
115
	dump_node_vcgattr_hook = hook;
116
}
117

118
void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
119
{
120
	dump_edge_vcgattr_hook = hook;
121
}
122

123
void ir_set_dump_flags(ir_dump_flags_t new_flags)
124
{
125
	flags = new_flags;
126
127
}

128
void ir_add_dump_flags(ir_dump_flags_t new_flags)
129
{
130
	flags |= new_flags;
131
132
}

133
void ir_remove_dump_flags(ir_dump_flags_t to_remove)
134
{
135
	flags &= ~to_remove;
Michael Beck's avatar
Michael Beck committed
136
137
}

138
ir_dump_flags_t ir_get_dump_flags(void)
139
{
140
	return flags;
141
142
}

143
144
/** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
 * are set, else returns dump_const_local_flag.
145
 */
146
static bool get_opt_dump_const_local(void)
147
{
148
149
150
151
	return (flags & ir_dump_flag_out_edges)
		|| (flags & ir_dump_flag_loops)
		|| (flags & ir_dump_flag_consts_local)
		|| (flags & ir_dump_flag_iredges);
152
153
}

154
static char *dump_filter;
155

156
void ir_set_dump_filter(const char *new_filter)
157
{
158
159
	xfree(dump_filter);
	dump_filter = xstrdup(new_filter);
160
161
}

162
const char *ir_get_dump_filter(void)
163
{
164
	return dump_filter;
165
166
}

167
int ir_should_dump(const char *name)
168
{
169
	const char *f, *n;
170

171
172
173
174
175
176
177
178
179
	if (dump_filter == NULL || dump_filter[0] == '\0')
		return 1;

	for (n = name, f = dump_filter; *f != '\0' && *n != '\0';
			++n, ++f) {
		if (*n != *f)
			return 0;
	}
	return 1;
180
181
}

182
183
/* -------------- some extended helper functions ----------------- */

184
185
const char *get_mode_name_ex(const ir_mode *mode, int *bad)
{
186
187
	if (is_mode(mode))
		return get_mode_name(mode);
188
189
190
	if (bad != NULL)
		*bad |= 1;
	return "<ERROR>";
191
192
}

193
194
195
196
197
#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
198
/** define a custom color. */
199
200
201
202
203
204
205
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;
206
	color_names[num] = (const char*)obstack_finish(&color_obst);
207
208
}

Michael Beck's avatar
Michael Beck committed
209
/** Define a named color. */
210
211
212
213
214
215
216
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
217
/** Initializes the used colors. */
218
219
220
static void init_colors(void)
{
	static int initialized = 0;
Michael Beck's avatar
Michael Beck committed
221
	if (initialized)
222
223
224
225
226
227
228
229
230
231
232
233
234
		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");
235
	custom_color(ird_color_uses_memory,           "153 153 255");
236
237
238
	custom_color(ird_color_phi,                   "105 255 105");
	custom_color(ird_color_anchor,                "100 100 255");
	named_color(ird_color_error,                  "red");
239
	custom_color(ird_color_entity,                "204 204 255");
240
241
242
243

	initialized = 1;
}

244
/**
245
 * Prints the VCG color to a file.
246
 */
247
static void print_vcg_color(FILE *out, ird_color_t color)
248
{
249
	assert(color < ird_color_count);
250
	fprintf(out, "color:%s", color_names[color]);
251
252
}

253
254
255
256
257
/**
 * Prints the edge kind of a given IR node.
 *
 * Projs should be dumped near their predecessor, so they get "nearedge".
 */
258
static void print_node_edge_kind(FILE *out, ir_node *node)
259
{
260
	if (is_Proj(node)) {
261
		fprintf(out, "nearedge: ");
262
	} else {
263
		fprintf(out, "edge: ");
264
265
266
	}
}

Michael Beck's avatar
Michael Beck committed
267
/**
268
269
 * 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
270
 */
Michael Beck's avatar
Michael Beck committed
271
static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
272
{
273
	va_list ap;
274

275
276
277
	va_start(ap, fmt);
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(S);
	fprintf(F, " targetname: "); PRINT_TYPEID(T);
278
	ir_vfprintf(F, fmt, ap);
279
280
	fprintf(F,"}\n");
	va_end(ap);
281
282
}

Michael Beck's avatar
Michael Beck committed
283
/**
Michael Beck's avatar
Michael Beck committed
284
 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
285
 * to the file F.
Michael Beck's avatar
Michael Beck committed
286
 */
Michael Beck's avatar
Michael Beck committed
287
static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
288
{
289
	va_list ap;
290

291
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
292
293
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
	fprintf(F, " targetname: \""); PRINT_ENTID(ent); fprintf(F, "\"");
294
	ir_vfprintf(F, fmt, ap);
295
296
	fprintf(F, "}\n");
	va_end(ap);
297
298
}

Michael Beck's avatar
Michael Beck committed
299
/**
Michael Beck's avatar
Michael Beck committed
300
 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
301
 * to the file F.
Michael Beck's avatar
Michael Beck committed
302
 */
Michael Beck's avatar
Michael Beck committed
303
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, ...)
304
{
305
	va_list ap;
306

307
308
309
310
311
	va_start(ap, fmt);
	if (backedge)
		fprintf(F, "backedge: { sourcename: \"");
	else
		fprintf(F, "edge: { sourcename: \"");
Michael Beck's avatar
Michael Beck committed
312
313
	PRINT_ENTID(ent1);
	fprintf(F, "\" targetname: \""); PRINT_ENTID(ent2);  fprintf(F, "\"");
314
	ir_vfprintf(F, fmt, ap);
315
	fprintf(F, " ");
316
	if (color != ird_color_none)
317
		print_vcg_color(F, color);
318
319
	fprintf(F, "}\n");
	va_end(ap);
320
321
}

Michael Beck's avatar
Michael Beck committed
322
/**
Michael Beck's avatar
Michael Beck committed
323
 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
324
 * to the file F.
Michael Beck's avatar
Michael Beck committed
325
 */
Michael Beck's avatar
Michael Beck committed
326
static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
327
{
328
	va_list ap;
329

330
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
331
332
	fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
	fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
333
	ir_vfprintf(F, fmt, ap);
334
335
	fprintf(F,"}\n");
	va_end(ap);
336
337
}

Michael Beck's avatar
Michael Beck committed
338
/**
Michael Beck's avatar
Michael Beck committed
339
 * Prints the edge from a node irn to a type tp with additional info fmt, ...
340
 * to the file F.
Michael Beck's avatar
Michael Beck committed
341
 */
Michael Beck's avatar
Michael Beck committed
342
static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
343
{
344
	va_list ap;
345

346
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
347
348
	fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
	fprintf(F, "\" targetname: "); PRINT_TYPEID(tp);
349
	ir_vfprintf(F, fmt, ap);
350
351
	fprintf(F,"}\n");
	va_end(ap);
352
353
}

Michael Beck's avatar
Michael Beck committed
354
/**
Michael Beck's avatar
Michael Beck committed
355
 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
356
 * to the file F.
Michael Beck's avatar
Michael Beck committed
357
 */
Michael Beck's avatar
Michael Beck committed
358
static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
359
{
360
	va_list ap;
361

362
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
363
364
	fprintf(F, "edge: { sourcename: \""); PRINT_NODEID(irn);
	fprintf(F, "\" targetname: \""); PRINT_ENTID(ent);
365
	fprintf(F, "\"");
366
	ir_vfprintf(F, fmt, ap);
367
368
	fprintf(F,"}\n");
	va_end(ap);
369
370
}

Michael Beck's avatar
Michael Beck committed
371
/**
Michael Beck's avatar
Michael Beck committed
372
 * Prints the edge from an entity ent to a node irn with additional info fmt, ...
373
 * to the file F.
Michael Beck's avatar
Michael Beck committed
374
 */
Michael Beck's avatar
Michael Beck committed
375
static void print_ent_node_edge(FILE *F, const ir_entity *ent, const ir_node *irn, const char *fmt, ...)
376
{
377
	va_list ap;
378

379
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
380
381
	fprintf(F, "edge: { sourcename: \""); PRINT_ENTID(ent);
	fprintf(F, "\" targetname: \""); PRINT_NODEID(irn); fprintf(F, "\"");
382
	ir_vfprintf(F, fmt, ap);
383
384
	fprintf(F,"}\n");
	va_end(ap);
385
}
386

Michael Beck's avatar
Michael Beck committed
387
/**
Michael Beck's avatar
Michael Beck committed
388
 * Prints the edge from a type tp to an enumeration item item with additional info fmt, ...
389
 * to the file F.
Michael Beck's avatar
Michael Beck committed
390
 */
391
static void print_enum_item_edge(FILE *F, const ir_type *tp, size_t item, const char *fmt, ...)
392
{
393
	va_list ap;
394

395
	va_start(ap, fmt);
Michael Beck's avatar
Michael Beck committed
396
397
	fprintf(F, "edge: { sourcename: "); PRINT_TYPEID(tp);
	fprintf(F, " targetname: \""); PRINT_ITEMID(tp, item); fprintf(F, "\" ");
398
	ir_vfprintf(F, fmt, ap);
399
400
	fprintf(F,"}\n");
	va_end(ap);
401
402
}

Michael Beck's avatar
Michael Beck committed
403
/*-----------------------------------------------------------------*/
404
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
405
/*-----------------------------------------------------------------*/
406

407
408
static void dump_node_with_edges(ir_node *n, void *env);
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
409

Michael Beck's avatar
Michael Beck committed
410
/*-----------------------------------------------------------------*/
411
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
412
/*-----------------------------------------------------------------*/
413

Michael Beck's avatar
Michael Beck committed
414
415
416
417
/**
 * This map is used as a private link attr to be able to call dumper
 * anywhere without destroying link fields.
 */
418
419
static pmap *irdump_link_map = NULL;

420
421
422
423
/** 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
424
 * initialization is performed lazily and not called from within init_firm.
425
 *
Michael Beck's avatar
Michael Beck committed
426
 * Creates the link attribute map. */
427
428
static void init_irdump(void)
{
429
430
431
432
433
	/* 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("");
434
}
435

Michael Beck's avatar
Michael Beck committed
436
437
438
/**
 * Returns the private link field.
 */
439
440
static void *ird_get_irn_link(const ir_node *n)
{
441
	void *res = NULL;
Michael Beck's avatar
Michael Beck committed
442
443
	if (irdump_link_map == NULL)
		return NULL;
444

Michael Beck's avatar
Michael Beck committed
445
446
	if (pmap_contains(irdump_link_map, n))
		res = pmap_get(irdump_link_map, n);
447
	return res;
448
449
}

Michael Beck's avatar
Michael Beck committed
450
451
452
/**
 * Sets the private link field.
 */
453
454
static void ird_set_irn_link(const ir_node *n, void *x)
{
Michael Beck's avatar
Michael Beck committed
455
	if (irdump_link_map == NULL)
456
		init_irdump();
Michael Beck's avatar
Michael Beck committed
457
	pmap_insert(irdump_link_map, n, x);
458
459
}

Michael Beck's avatar
Michael Beck committed
460
461
462
/**
 * Gets the private link field of an irg.
 */
463
464
static void *ird_get_irg_link(const ir_graph *irg)
{
465
	void *res = NULL;
Michael Beck's avatar
Michael Beck committed
466
467
	if (irdump_link_map == NULL)
		return NULL;
468

Michael Beck's avatar
Michael Beck committed
469
470
	if (pmap_contains(irdump_link_map, irg))
		res = pmap_get(irdump_link_map, irg);
471
	return res;
472
473
}

Michael Beck's avatar
Michael Beck committed
474
475
476
/**
 * Sets the private link field of an irg.
 */
477
478
static void ird_set_irg_link(const ir_graph *irg, void *x)
{
Michael Beck's avatar
Michael Beck committed
479
480
481
	if (irdump_link_map == NULL)
		init_irdump();
	pmap_insert(irdump_link_map, irg, x);
482
483
}

Michael Beck's avatar
Michael Beck committed
484
/**
485
 * Walker, clears the private link field.
Michael Beck's avatar
Michael Beck committed
486
 */
487
488
static void clear_link(ir_node *node, void *env)
{
489
	(void) env;
490
	ird_set_irn_link(node, NULL);
491
492
}

Michael Beck's avatar
Michael Beck committed
493
/**
494
 * If the entity has a ld_name, returns it if the dump_ld_name is set,
495
 * else returns the name of the entity.
Michael Beck's avatar
Michael Beck committed
496
 */
497
static const char *_get_ent_dump_name(const ir_entity *ent, bool dump_ld_name)
498
{
Michael Beck's avatar
Michael Beck committed
499
	if (ent == NULL)
500
501
502
		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
503
504
		if (ent->ld_name != NULL)
			return get_id_str(ent->ld_name);
505
506
	}
	return get_id_str(ent->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
507
508
}

509
510
const char *get_ent_dump_name(const ir_entity *ent)
{
511
	return _get_ent_dump_name(ent, flags & ir_dump_flag_ld_names);
512
513
}

514
515
const char *get_irg_dump_name(const ir_graph *irg)
{
516
	/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
517
	return _get_ent_dump_name(get_irg_entity(irg), true);
518
519
}

520
521
522
/**
 * Returns non-zero if a node is in floating state.
 */
523
524
static int node_floats(const ir_node *n)
{
525
526
	return ((get_irn_pinned(n) == op_pin_state_floats) &&
	        (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
527
528
}

529
530
531
/**
 *  Walker that visits the anchors
 */
532
533
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
{
534
535
	if ((flags & ir_dump_flag_all_anchors)
			|| ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
Michael Beck's avatar
Michael Beck committed
536
		irg_walk_anchors(irg, pre, post, env);
537
538
	} else {
		irg_walk_graph(irg, pre, post, env);
539
	}
540
541
}

Michael Beck's avatar
Michael Beck committed
542
/**
543
 * Walker, allocates an array for all blocks and puts their non-floating
544
 * nodes into this array.
Michael Beck's avatar
Michael Beck committed
545
 */
546
547
static void collect_node(ir_node *node, void *env)
{
548
	(void) env;
549
550
	if (is_Block(node)
	    || node_floats(node)
551
	    || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
		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);
		}
	}
570
571
572
573
}

/** Construct lists to walk ir block-wise.
 *
574
 * Collects all blocks, nodes not op_pin_state_pinned,
575
 * Bad, NoMem and Unknown into a flexible array in link field of
576
577
 * irg they belong to.  Sets the irg link field to NULL in all
 * graphs not visited.
Michael Beck's avatar
Michael Beck committed
578
579
 * Free the list with DEL_ARR_F().
 */
580
581
static ir_node **construct_block_lists(ir_graph *irg)
{
582
	size_t   i;
583
	int      walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
584
585
	ir_graph *rem      = current_ir_graph;

586
	current_ir_graph = irg;
587

588
	if (walk_flag) {
589
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
590
	}
591

592
593
	for (i = get_irp_n_irgs(); i > 0;)
		ird_set_irg_link(get_irp_irg(--i), NULL);
594

595
	ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
596

Michael Beck's avatar
Michael Beck committed
597
	if (walk_flag) {
598
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
599
	}
600

601
	current_ir_graph = rem;
602
	return (ir_node**)ird_get_irg_link(irg);
603
604
}

605
typedef struct list_tuple {
606
607
	ir_node **blk_list;
	ir_extblk **extbb_list;
608
609
} list_tuple;

610
/** Construct lists to walk IR extended block-wise.
611
612
 * Free the lists in the tuple with DEL_ARR_F(). Sets the irg link field to
 * NULL in all graphs not visited.
613
 */
614
615
static list_tuple *construct_extblock_lists(ir_graph *irg)
{
616
	ir_node **blk_list = construct_block_lists(irg);
617
	size_t i, n;
618
	ir_graph *rem = current_ir_graph;
619
	list_tuple *lists = XMALLOC(list_tuple);
620

621
	current_ir_graph = irg;
622

623
624
	lists->blk_list   = NEW_ARR_F(ir_node *, 0);
	lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
625

626
	inc_irg_block_visited(irg);
627
	for (i = 0, n = ARR_LEN(blk_list); i < n; ++i) {
628
		ir_extblk *ext;
629

630
631
		if (is_Block(blk_list[i])) {
			ext = get_Block_extbb(blk_list[i]);
632

633
634
635
636
637
638
639
640
			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);
641

642
643
644
	current_ir_graph = rem;
	ird_set_irg_link(irg, lists);
	return lists;
645
646
}

647
void dump_node_opcode(FILE *F, ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
648
{
649
650
651
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
652
653
654
655
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_opcode_txt);
		return;
	}
656
657
658

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
659
	case iro_SymConst:
660
661
662
663
664
665
666
667
		switch (get_SymConst_kind(n)) {
		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:
668
			ir_fprintf(F, "SymC %+F tag", get_SymConst_type(n));
669
670
			break;
		case symconst_type_size:
671
			ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
672
673
			break;
		case symconst_type_align:
674
			ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
675
676
			break;
		case symconst_enum_const:
677
			fprintf(F, "SymC %s enum", get_enumeration_const_name(get_SymConst_enum(n)));
678
679
			break;
		}
680
		break;
681
682
683
684
685

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

		if (get_irn_opcode(pred) == iro_Cond
686
			&& get_Proj_proj(n) == get_Cond_default_proj(pred)
687
688
689
690
691
			&& get_irn_mode(get_Cond_selector(pred)) != mode_b)
			fprintf(F, "defProj");
		else
			goto default_case;
	} break;
692

693
	case iro_Load:
694
		if (get_Load_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
695
			fprintf(F, "ua");
696
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), NULL));
697
		break;
Michael Beck's avatar
Michael Beck committed
698
	case iro_Store:
699
		if (get_Store_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
700
701
702
			fprintf(F, "ua");
		fprintf(F, "%s", get_irn_opname(n));
		break;
703
	case iro_Block:
704
705
706
707
708
709
710
		if (is_Block_dead(n))
			fputs("Dead ", F);
		if (n == get_irg_start_block(get_irn_irg(n)))
			fputs("Start ", F);
		if (n == get_irg_end_block(get_irn_irg(n)))
			fputs("End ", F);
		fprintf(F, "%s%s", get_irn_opname(n),
711
			(flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
712
713
714
715
716
717
		break;
	case iro_Conv:
		if (get_Conv_strict(n))
			fprintf(F, "strict");
		fprintf(F, "%s", get_irn_opname(n));
		break;
718
	case iro_Div:
719
		fprintf(F, "%s", get_irn_opname(n));
720
		if (get_Div_no_remainder(n))
721
			fprintf(F, "RL");
722
		fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n), NULL));
723
724
		break;
	case iro_Mod:
725
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), NULL));
726
		break;
727
728
729
	case iro_Builtin:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
		break;
730
731

	default:
732
default_case:
733
		fprintf(F, "%s", get_irn_opname(n));
734
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
735
736
}

Michael Beck's avatar
Michael Beck committed
737
738
739
740
/**
 * Dump the mode of a node n to a file F.
 * Ignore modes that are "always known".
 */
741
static void dump_node_mode(FILE *F, ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
742
{
743
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
744
	unsigned         iro;
Michael Beck's avatar
Michael Beck committed
745
	ir_mode         *mode;
746
747

	/* call the dump_node operation if available */
748
749
750
751
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_mode_txt);
		return;
	}
752
753
754
755
756
757
758
759
760
761
762
763
764

	/* 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
765
766
	default:
		mode = get_irn_mode(n);
767

Michael Beck's avatar
Michael Beck committed
768
		if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
769
			(mode != mode_T || iro == iro_Proj))
770
			fprintf(F, "%s", get_mode_name_ex(mode, NULL));
771
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
772
773
}

Michael Beck's avatar
Michael Beck committed
774
/**
775
 * Dump the type of a node n to a file F if it's known.
Michael Beck's avatar
Michael Beck committed
776
 */
777
778
static int dump_node_typeinfo(FILE *F, ir_node *n)
{
779
780
	int bad = 0;

781
	if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
782
783
784
		if (get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_consistent  ||
			get_irg_typeinfo_state(current_ir_graph) == ir_typeinfo_inconsistent) {
			ir_type *tp = get_irn_typeinfo_type(n);
785
786
787
			if (tp != firm_none_type) {
				ir_fprintf(F, "[%+F]", tp);
			} else {
788
				fprintf(F, "[] ");
789
			}
790
791
792
		}
	}
	return bad;
793
794
}

795
typedef struct pns_lookup {
796
797
	long       nr;      /**< the proj number */
	const char *name;   /**< the name of the Proj */
798
799
} pns_lookup_t;

800
typedef struct proj_lookup {