irdump.c 60.7 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
/**
 * @file
 * @brief   Write vcg representation of firm to file.
9
10
 * @author  Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt,
 *          Matthias Braun
Götz Lindenmaier's avatar
Götz Lindenmaier committed
11
 */
12
13
14
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
15
16
#include <stdbool.h>
#include <errno.h>
17

18
19
#include "irnode_t.h"
#include "irgraph_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
20
#include "irprog_t.h"
21
#include "entity_t.h"
22
#include "irop.h"
23

24
#include "irdump_t.h"
25
26
27
28

#include "irgwalk.h"
#include "tv_t.h"
#include "irouts.h"
Michael Beck's avatar
Michael Beck committed
29
#include "iredges.h"
30
#include "irdom.h"
Michael Beck's avatar
Michael Beck committed
31
#include "irloop_t.h"
32
#include "callgraph.h"
33
#include "irhooks.h"
Michael Beck's avatar
Michael Beck committed
34
#include "dbginfo_t.h"
35
#include "irprintf.h"
36

37
#include "irverify.h"
38

39
#include "error.h"
40
41
#include "array.h"
#include "pmap.h"
42
#include "obst.h"
43
#include "pset.h"
44
#include "util.h"
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
 * Symbolic names for the different dumping colors.
 */
typedef enum ird_color_t {
	ird_color_none = -1,
	ird_color_prog_background,
	ird_color_block_background,
	ird_color_block_inout,
	ird_color_default_node,
	ird_color_phi,
	ird_color_memory,
	ird_color_controlflow,
	ird_color_const,
	ird_color_anchor,
	ird_color_proj,
	ird_color_uses_memory,
	ird_color_error,
	ird_color_entity,
	ird_color_count
} ird_color_t;

/* Attributes of nodes */
#define PRINT_DEFAULT_NODE_ATTR
#define DEFAULT_NODE_ATTR " "
#define DEFAULT_TYPE_ATTRIBUTE " "
#define DEFAULT_ENUM_ITEM_ATTRIBUTE " "

/* Attributes of edges between Firm nodes */
#define INTRA_DATA_EDGE_ATTR     "class:1  priority:50"
#define INTER_DATA_EDGE_ATTR     "class:16 priority:10"
#define BLOCK_EDGE_ATTR          "class:2  priority:50 linestyle:dotted"
#define CF_EDGE_ATTR             "class:13 priority:60 color:red"
#define EXC_CF_EDGE_ATTR         "class:18 priority:60 color:blue"
#define INTRA_MEM_EDGE_ATTR      "class:14 priority:50 color:blue"
#define INTER_MEM_EDGE_ATTR      "class:17 priority:10 color:blue"
#define DOMINATOR_EDGE_ATTR      "class:15 color:red"
#define POSTDOMINATOR_EDGE_ATTR  "class:19 color:red linestyle:dotted"
#define KEEP_ALIVE_EDGE_ATTR     "class:20 priority:10 color:purple"
#define KEEP_ALIVE_CF_EDGE_ATTR  "class:20 priority:60 color:purple"
#define KEEP_ALIVE_DF_EDGE_ATTR  "class:20 priority:10 color:purple"
#define ANCHOR_EDGE_ATTR         "class:20 priority:60 color:purple linestyle:dotted"
#define OUT_EDGE_ATTR            "class:21 priority:10 color:gold linestyle:dashed"

#define BACK_EDGE_ATTR "linestyle:dashed "

/* Attributes of edges between Firm nodes and type/entity nodes */
#define NODE2TYPE_EDGE_ATTR "class:2 priority:2 linestyle:dotted"

/* Attributes of edges in type/entity graphs. */
#define TYPE_METH_NODE_ATTR      "color: lightyellow"
#define TYPE_CLASS_NODE_ATTR     "color: green"
#define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
#define ENTITY_NODE_ATTR         "color: yellow"
#define ENUM_ITEM_NODE_ATTR      "color: green"
#define ENT_TYPE_EDGE_ATTR       "class: 3 label: \"type\" color: red"
#define ENT_OWN_EDGE_ATTR        "class: 4 label: \"owner\" color: black"
#define METH_PAR_EDGE_ATTR       "class: 5 label: \"param %zu\" color: green"
#define METH_RES_EDGE_ATTR       "class: 6 label: \"res %zu\" color: green"
#define TYPE_SUPER_EDGE_ATTR     "class: 7 label: \"supertype\" color: red"
#define UNION_EDGE_ATTR          "class: 8 label: \"component\" color: blue"
#define PTR_PTS_TO_EDGE_ATTR     "class: 9 label: \"points to\" color:green"
#define ARR_ELT_TYPE_EDGE_ATTR   "class: 10 label: \"arr elt tp\" color:green"
#define ARR_ENT_EDGE_ATTR        "class: 10 label: \"arr ent\" color: green"
#define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
#define ENT_VALUE_EDGE_ATTR      "label: \"value %d\""
#define ENT_CORR_EDGE_ATTR       "label: \"value %zu corresponds to \" "
#define TYPE_MEMBER_EDGE_ATTR    "class: 12 label: \"member\" color:blue"
/* #define CALLGRAPH_EDGE_ATTR      "calls" */

115
116
117
118
119
120
121
122
123
124
125
126
127
typedef struct pns_lookup {
	long       nr;      /**< the proj number */
	const char *name;   /**< the name of the Proj */
} pns_lookup_t;

typedef struct proj_lookup {
	unsigned           code;      /**< the opcode of the Proj predecessor */
	unsigned           num_data;  /**< number of data entries */
	const pns_lookup_t *data;     /**< the data */
} proj_lookup_t;

#include "gen_irdump.c.inl"

128
/** Dump only irgs with names that start with this prefix. */
129
130
static ident *dump_file_filter_id = NULL;

131
132
133
134
135
136
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 |
Matthias Braun's avatar
Matthias Braun committed
137
138
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
139

140
static ird_color_t overrule_nodecolor = ird_color_default_node;
141

142
/** The vcg node attribute hook. */
143
static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
144
/** The vcg edge attribute hook. */
145
static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
146
/** The vcg dump block edge hook */
147
static dump_node_edge_func dump_block_edge_hook = NULL;
148
/** The vcg dump node edge hook. */
149
static dump_node_edge_func dump_node_edge_hook = NULL;
150

151
void set_dump_node_edge_hook(dump_node_edge_func func)
152
{
153
	dump_node_edge_hook = func;
154
155
}

156
dump_node_edge_func get_dump_node_edge_hook(void)
157
{
158
	return dump_node_edge_hook;
159
160
}

161
void set_dump_block_edge_hook(dump_node_edge_func func)
162
{
163
	dump_block_edge_hook = func;
164
165
}

166
dump_node_edge_func get_dump_block_edge_hook(void)
167
{
168
	return dump_node_edge_hook;
169
170
}

171
void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
172
{
173
	dump_node_vcgattr_hook = hook;
174
}
175

176
void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
177
{
178
	dump_edge_vcgattr_hook = hook;
179
}
180

181
void ir_set_dump_flags(ir_dump_flags_t new_flags)
182
{
183
	flags = new_flags;
184
185
}

186
void ir_add_dump_flags(ir_dump_flags_t new_flags)
187
{
188
	flags |= new_flags;
189
190
}

191
void ir_remove_dump_flags(ir_dump_flags_t to_remove)
192
{
193
	flags &= ~to_remove;
Michael Beck's avatar
Michael Beck committed
194
195
}

196
ir_dump_flags_t ir_get_dump_flags(void)
197
{
198
	return flags;
199
200
}

201
202
/** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
 * are set, else returns dump_const_local_flag.
203
 */
204
static bool get_opt_dump_const_local(void)
205
{
206
207
208
209
	return (flags & ir_dump_flag_out_edges)
		|| (flags & ir_dump_flag_loops)
		|| (flags & ir_dump_flag_consts_local)
		|| (flags & ir_dump_flag_iredges);
210
211
}

212
static char *dump_filter;
213

214
void ir_set_dump_filter(const char *new_filter)
215
{
216
	free(dump_filter);
217
	dump_filter = xstrdup(new_filter);
218
219
}

220
const char *ir_get_dump_filter(void)
221
{
222
	return dump_filter;
223
224
}

225
226
/** Returns true if dump file filter is not set, or if it is a prefix of name. */
static int ir_should_dump(const char *name)
227
{
228
	if (!dump_filter)
229
230
		return 1;

231
	for (char const *n = name, *f = dump_filter; *f != '\0'; ++n, ++f) {
232
233
234
235
		if (*n != *f)
			return 0;
	}
	return 1;
236
237
}

238
239
/* -------------- some extended helper functions ----------------- */

240
241
242
243
244
#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
245
/** define a custom color. */
246
247
248
249
250
251
252
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;
253
	color_names[num] = (const char*)obstack_finish(&color_obst);
254
255
}

Michael Beck's avatar
Michael Beck committed
256
/** Define a named color. */
257
258
259
260
261
262
263
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
264
/** Initializes the used colors. */
265
266
static void init_colors(void)
{
267
	static bool initialized = 0;
Michael Beck's avatar
Michael Beck committed
268
	if (initialized)
269
270
271
272
		return;

	obstack_init(&color_obst);

273
274
275
276
277
278
279
280
281
282
283
284
285
	custom_color(ird_color_prog_background,  "204 204 204");
	custom_color(ird_color_block_background, "255 255 0");
	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");
	custom_color(ird_color_uses_memory,      "153 153 255");
	custom_color(ird_color_phi,              "105 255 105");
	custom_color(ird_color_anchor,           "100 100 255");
	named_color(ird_color_error,             "red");
	custom_color(ird_color_entity,           "204 204 255");
286
287
288
289

	initialized = 1;
}

290
/**
291
 * Prints the VCG color to a file.
292
 */
293
static void print_vcg_color(FILE *out, ird_color_t color)
294
{
295
	assert(color < ird_color_count);
296
	fprintf(out, "color:%s", color_names[color]);
297
298
}

299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
void print_nodeid(FILE *F, const ir_node *node)
{
	fprintf(F, "\"n%ld\"", get_irn_node_nr(node));
}

void print_irgid(FILE *F, const ir_graph *irg)
{
	fprintf(F, "\"g%ld\"", get_irg_graph_nr(irg));
}

void print_typeid(FILE *F, const ir_type *type)
{
	fprintf(F, "\"t%ld\"", get_type_nr(type));
}

void print_entityid(FILE *F, const ir_entity *entity)
{
	fprintf(F, "\"e%ld\"", get_entity_nr(entity));
}

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

Michael Beck's avatar
Michael Beck committed
333
/**
334
335
 * 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
336
 */
Michael Beck's avatar
Michael Beck committed
337
static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
338
{
339
	va_list ap;
340

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

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

359
	va_start(ap, fmt);
360
361
362
363
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, tp);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
364
	ir_vfprintf(F, fmt, ap);
365
366
	fprintf(F, "}\n");
	va_end(ap);
367
368
}

Michael Beck's avatar
Michael Beck committed
369
/**
Michael Beck's avatar
Michael Beck committed
370
 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
371
 * to the file F.
Michael Beck's avatar
Michael Beck committed
372
 */
Michael Beck's avatar
Michael Beck committed
373
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, ...)
374
{
375
	va_list ap;
376

377
378
	va_start(ap, fmt);
	if (backedge)
379
		fprintf(F, "backedge: { sourcename: ");
380
	else
381
382
383
384
		fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent1);
	fprintf(F, " targetname: ");
	print_entityid(F, ent2);
385
	ir_vfprintf(F, fmt, ap);
386
	fprintf(F, " ");
387
	if (color != ird_color_none)
388
		print_vcg_color(F, color);
389
390
	fprintf(F, "}\n");
	va_end(ap);
391
392
}

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

401
	va_start(ap, fmt);
402
403
404
405
	fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
406
	ir_vfprintf(F, fmt, ap);
407
408
	fprintf(F,"}\n");
	va_end(ap);
409
410
}

Michael Beck's avatar
Michael Beck committed
411
/**
Michael Beck's avatar
Michael Beck committed
412
 * Prints the edge from a node irn to a type tp with additional info fmt, ...
413
 * to the file F.
Michael Beck's avatar
Michael Beck committed
414
 */
Michael Beck's avatar
Michael Beck committed
415
static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
416
{
417
	va_list ap;
418

419
	va_start(ap, fmt);
420
421
422
423
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
424
	ir_vfprintf(F, fmt, ap);
425
426
	fprintf(F,"}\n");
	va_end(ap);
427
428
}

Michael Beck's avatar
Michael Beck committed
429
/**
Michael Beck's avatar
Michael Beck committed
430
 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
431
 * to the file F.
Michael Beck's avatar
Michael Beck committed
432
 */
Michael Beck's avatar
Michael Beck committed
433
static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
434
{
435
	va_list ap;
436

437
	va_start(ap, fmt);
438
439
440
441
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
442
	ir_vfprintf(F, fmt, ap);
443
444
	fprintf(F,"}\n");
	va_end(ap);
445
446
}

Michael Beck's avatar
Michael Beck committed
447
/*-----------------------------------------------------------------*/
448
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
449
/*-----------------------------------------------------------------*/
450

451
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
452

Michael Beck's avatar
Michael Beck committed
453
/*-----------------------------------------------------------------*/
454
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
455
/*-----------------------------------------------------------------*/
456

Michael Beck's avatar
Michael Beck committed
457
458
459
460
/**
 * This map is used as a private link attr to be able to call dumper
 * anywhere without destroying link fields.
 */
461
462
static pmap *irdump_link_map = NULL;

463
464
465
466
/** 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
467
 * initialization is performed lazily and not called from within init_firm.
468
 *
Michael Beck's avatar
Michael Beck committed
469
 * Creates the link attribute map. */
470
471
static void init_irdump(void)
{
472
473
474
475
476
	/* 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("");
477
}
478

Michael Beck's avatar
Michael Beck committed
479
480
481
/**
 * Returns the private link field.
 */
482
483
static void *ird_get_irn_link(const ir_node *n)
{
Michael Beck's avatar
Michael Beck committed
484
485
	if (irdump_link_map == NULL)
		return NULL;
486

487
	return pmap_get(void, irdump_link_map, n);
488
489
}

Michael Beck's avatar
Michael Beck committed
490
491
492
/**
 * Sets the private link field.
 */
493
494
static void ird_set_irn_link(const ir_node *n, void *x)
{
Michael Beck's avatar
Michael Beck committed
495
	if (irdump_link_map == NULL)
496
		init_irdump();
Michael Beck's avatar
Michael Beck committed
497
	pmap_insert(irdump_link_map, n, x);
498
499
}

Michael Beck's avatar
Michael Beck committed
500
501
502
/**
 * Gets the private link field of an irg.
 */
503
504
static void *ird_get_irg_link(const ir_graph *irg)
{
Michael Beck's avatar
Michael Beck committed
505
506
	if (irdump_link_map == NULL)
		return NULL;
507

508
	return pmap_get(void, irdump_link_map, irg);
509
510
}

Michael Beck's avatar
Michael Beck committed
511
512
513
/**
 * Sets the private link field of an irg.
 */
514
515
static void ird_set_irg_link(const ir_graph *irg, void *x)
{
Michael Beck's avatar
Michael Beck committed
516
517
518
	if (irdump_link_map == NULL)
		init_irdump();
	pmap_insert(irdump_link_map, irg, x);
519
520
}

Michael Beck's avatar
Michael Beck committed
521
/**
522
 * Walker, clears the private link field.
Michael Beck's avatar
Michael Beck committed
523
 */
524
525
static void clear_link(ir_node *node, void *env)
{
526
	(void) env;
527
	ird_set_irn_link(node, NULL);
528
529
}

Michael Beck's avatar
Michael Beck committed
530
/**
531
 * If the entity has a ld_name, returns it if the dump_ld_name is set,
532
 * else returns the name of the entity.
Michael Beck's avatar
Michael Beck committed
533
 */
534
static const char *get_ent_dump_name_(const ir_entity *ent, bool dump_ld_name)
535
{
Michael Beck's avatar
Michael Beck committed
536
	if (ent == NULL)
537
538
539
		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
540
541
		if (ent->ld_name != NULL)
			return get_id_str(ent->ld_name);
542
543
	}
	return get_id_str(ent->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
544
545
}

546
547
const char *get_ent_dump_name(const ir_entity *ent)
{
548
	return get_ent_dump_name_(ent, flags & ir_dump_flag_ld_names);
549
550
}

551
552
const char *get_irg_dump_name(const ir_graph *irg)
{
553
	/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
554
	return get_ent_dump_name_(get_irg_entity(irg), true);
555
556
}

557
558
559
/**
 * Returns non-zero if a node is in floating state.
 */
560
561
static int node_floats(const ir_node *n)
{
562
	ir_graph *irg = get_irn_irg(n);
563
	return ((get_irn_pinned(n) == op_pin_state_floats) &&
564
	        (get_irg_pinned(irg) == op_pin_state_floats));
565
566
}

567
568
569
/**
 *  Walker that visits the anchors
 */
570
571
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
{
572
573
	if ((flags & ir_dump_flag_all_anchors)
			|| ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
Michael Beck's avatar
Michael Beck committed
574
		irg_walk_anchors(irg, pre, post, env);
575
576
	} else {
		irg_walk_graph(irg, pre, post, env);
577
	}
578
579
}

Michael Beck's avatar
Michael Beck committed
580
/**
581
 * Walker, allocates an array for all blocks and puts their non-floating
582
 * nodes into this array.
Michael Beck's avatar
Michael Beck committed
583
 */
584
585
static void collect_node(ir_node *node, void *env)
{
586
	(void) env;
587
588
	if (is_Block(node)
	    || node_floats(node)
589
	    || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
		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);
		}
	}
608
609
610
611
}

/** Construct lists to walk ir block-wise.
 *
612
 * Collects all blocks, nodes not op_pin_state_pinned,
613
 * Bad, NoMem and Unknown into a flexible array in link field of
614
615
 * irg they belong to.  Sets the irg link field to NULL in all
 * graphs not visited.
Michael Beck's avatar
Michael Beck committed
616
617
 * Free the list with DEL_ARR_F().
 */
618
619
static ir_node **construct_block_lists(ir_graph *irg)
{
620
	int const walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
621

622
	if (walk_flag) {
623
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
624
	}
625

626
627
628
	foreach_irp_irg_r(i, irg) {
		ird_set_irg_link(irg, NULL);
	}
629

630
	ird_walk_graph(irg, clear_link, collect_node, irg);
631

Michael Beck's avatar
Michael Beck committed
632
	if (walk_flag) {
633
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
634
	}
635

636
	return (ir_node**)ird_get_irg_link(irg);
637
638
}

639
void dump_node_opcode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
640
{
641
642
643
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
644
645
646
647
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_opcode_txt);
		return;
	}
648
649
650

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
651
652
653
654
655
656
	case iro_Address:
		fprintf(F, "Address &%s", get_entity_name(get_Address_entity(n)));
		break;

	case iro_Offset:
		fprintf(F, "Offset %s", get_entity_name(get_Offset_entity(n)));
657
658
		break;

659
660
661
662
663
664
	case iro_Align:
		ir_fprintf(F, "Align %+F", get_Align_type(n));
		break;

	case iro_Size:
		ir_fprintf(F, "Size %+F", get_Size_type(n));
665
		break;
666
667

	case iro_Load:
668
		if (get_Load_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
669
			fprintf(F, "ua");
Christoph Mallon's avatar
Christoph Mallon committed
670
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name(get_Load_mode(n)));
671
		break;
Michael Beck's avatar
Michael Beck committed
672
	case iro_Store:
673
		if (get_Store_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
674
675
676
			fprintf(F, "ua");
		fprintf(F, "%s", get_irn_opname(n));
		break;
677
	case iro_Block:
678
679
680
681
682
		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),
683
			(flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
684
		break;
685
	case iro_Div:
686
		fprintf(F, "%s", get_irn_opname(n));
687
		if (get_Div_no_remainder(n))
688
			fprintf(F, "RL");
Christoph Mallon's avatar
Christoph Mallon committed
689
		fprintf(F, "[%s]", get_mode_name(get_Div_resmode(n)));
690
691
		break;
	case iro_Mod:
Christoph Mallon's avatar
Christoph Mallon committed
692
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name(get_Mod_resmode(n)));
693
		break;
694
695
696
	case iro_Builtin:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
		break;
697
698
699

	default:
		fprintf(F, "%s", get_irn_opname(n));
700
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
701
702
}

Michael Beck's avatar
Michael Beck committed
703
704
705
706
/**
 * Dump the mode of a node n to a file F.
 * Ignore modes that are "always known".
 */
707
static void dump_node_mode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
708
{
709
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
710
	unsigned         iro;
Michael Beck's avatar
Michael Beck committed
711
	ir_mode         *mode;
712
713

	/* call the dump_node operation if available */
714
715
716
717
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_mode_txt);
		return;
	}
718
719
720
721

	/* default implementation */
	iro = get_irn_opcode(n);
	switch (iro) {
722
	case iro_Address:
723
	case iro_Align:
724
725
726
727
728
729
730
	case iro_Sel:
	case iro_End:
	case iro_Return:
	case iro_Free:
	case iro_Sync:
	case iro_Jmp:
	case iro_NoMem:
731
	case iro_Offset:
732
	case iro_Size:
733
		break;
Michael Beck's avatar
Michael Beck committed
734
735
	default:
		mode = get_irn_mode(n);
736

Michael Beck's avatar
Michael Beck committed
737
		if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
738
			(mode != mode_T || iro == iro_Proj))
Christoph Mallon's avatar
Christoph Mallon committed
739
			fprintf(F, "%s", get_mode_name(mode));
740
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
741
742
}

Michael Beck's avatar
Michael Beck committed
743
/**
744
 * Dump additional node attributes of some nodes to a file F.
Michael Beck's avatar
Michael Beck committed
745
 */
746
static void dump_node_nodeattr(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
747
{
748
	ir_node *pred;
749
	unsigned code;
750
751
752
753
	long proj_nr;
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
754
755
756
757
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_nodeattr_txt);
		return;
	}
758
759

	switch (get_irn_opcode(n)) {
760
761
762
763
	case iro_Const:
		ir_fprintf(F, "%T ", get_Const_tarval(n));
		break;

764
765
766
767
768
	case iro_Proj:
		pred    = get_Proj_pred(n);
		proj_nr = get_Proj_proj(n);
		code    = get_irn_opcode(pred);

769
		if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start) {
770
			fprintf(F, "Arg %ld ", proj_nr);
771
		} else {
772
773
			unsigned i, j, f = 0;

774
			for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
				if (code == proj_lut[i].code) {
					for (j = 0; j < proj_lut[i].num_data; ++j) {
						if (proj_nr == proj_lut[i].data[j].nr) {
							fprintf(F, "%s ", proj_lut[i].data[j].name);
							f = 1;
							break;
						}
					}
					break;
				}
			}
			if (! f)
				fprintf(F, "%ld ", proj_nr);
			if (code == iro_Cond && get_Cond_jmp_pred(pred) != COND_JMP_PRED_NONE) {
				if (proj_nr == pn_Cond_false && get_Cond_jmp_pred(pred) == COND_JMP_PRED_FALSE)
					fprintf(F, "PRED ");
				if (proj_nr == pn_Cond_true && get_Cond_jmp_pred(pred) == COND_JMP_PRED_TRUE)
					fprintf(F, "PRED ");
			}
		}
		break;
	case iro_Sel:
		fprintf(F, "%s ", get_ent_dump_name(get_Sel_entity(n)));
		break;
799
800
801
	case iro_Cmp:
		fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
		break;
802
	case iro_Confirm:
803
		fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
804
805
		break;
	case iro_CopyB:
806
		ir_fprintf(F, "(%+F)", get_CopyB_type(n));
807
808
809
		break;

	default:
810
		break;
811
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
812
813
}

814
void dump_node_label(FILE *F, const ir_node *n)
815
{
816
	dump_node_opcode(F, n);
817
	fputs(" ", F);
818
	dump_node_mode(F, n);
819
	fprintf(F, " ");
820
821
	dump_node_nodeattr(F, n);
	if (flags & ir_dump_flag_number_label) {
822
823
		fprintf(F, "%ld", get_irn_node_nr(n));
	}
824
	if (flags & ir_dump_flag_idx_label) {
825
826
		fprintf(F, ":%u", get_irn_idx(n));
	}
827
828
}

Michael Beck's avatar
Michael Beck committed
829
/**
830
 * Dumps the attributes of a node n into the file F.
Michael Beck's avatar
Michael Beck committed
831
832
 * Currently this is only the color of a node.
 */
833
static void dump_node_vcgattr(FILE *F, const ir_node *node, const ir_node *local)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
834
{
835
	ir_mode *mode;
836
	const ir_node *n;
837

838
	if (dump_node_vcgattr_hook != NULL) {
839
840
		if (dump_node_vcgattr_hook(F, node, local) != 0)
			return;
841
	}
842
843
844

	n = local ? local : node;

845
	if (overrule_nodecolor != ird_color_default_node) {
846
847
848
849
		print_vcg_color(F, overrule_nodecolor);
		return;
	}

850
	mode = get_irn_mode(n);
851
	if (mode == mode_M) {
852
853
854
		print_vcg_color(F, ird_color_memory);
		return;
	}
855
	if (mode == mode_X) {
856
857
858
859
		print_vcg_color(F, ird_color_controlflow);
		return;
	}

860
861
862
	switch (get_irn_opcode(n)) {
	case iro_Start:
	case iro_End:
863
864
865
866
		print_vcg_color(F, ird_color_anchor);
		break;
	case iro_Bad:
		print_vcg_color(F, ird_color_error);
867
868
		break;
	case iro_Block:
869
		print_vcg_color(F, ird_color_block_background);
870
871
		break;
	case iro_Phi:
872
		print_vcg_color(F, ird_color_phi);
873
874
		break;
	case iro_Pin:
875
		print_vcg_color(F, ird_color_memory);
876
		break;
877
878
	case iro_Proj:
		print_vcg_color(F, ird_color_proj);
Michael Beck's avatar
Michael Beck committed
879
		break;
880
	default: {
881
		ir_op *op = get_irn_op(n);
882

883
		if (is_op_constlike(op)) {