irdump.c 60.9 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
115
/**
 * 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_dead_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" */

116
117
118
119
120
121
122
123
124
125
126
127
128
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"

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

132
133
134
135
136
137
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
138
139
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
140

141
static ird_color_t overrule_nodecolor = ird_color_default_node;
142

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

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

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

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

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

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

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

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

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

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

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

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

213
static char *dump_filter;
214

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

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

226
227
/** 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)
228
{
229
	if (!dump_filter)
230
231
		return 1;

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

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

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

Michael Beck's avatar
Michael Beck committed
257
/** Define a named color. */
258
259
260
261
262
263
264
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
265
/** Initializes the used colors. */
266
267
static void init_colors(void)
{
268
	static bool initialized = 0;
Michael Beck's avatar
Michael Beck committed
269
	if (initialized)
270
271
272
273
274
275
276
277
278
279
280
281
282
		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");
283
	custom_color(ird_color_uses_memory,           "153 153 255");
284
285
286
	custom_color(ird_color_phi,                   "105 255 105");
	custom_color(ird_color_anchor,                "100 100 255");
	named_color(ird_color_error,                  "red");
287
	custom_color(ird_color_entity,                "204 204 255");
288
289
290
291

	initialized = 1;
}

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

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
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));
}

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

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

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

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

361
	va_start(ap, fmt);
362
363
364
365
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, tp);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
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 ent1 to an entity ent2 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_ent_edge(FILE *F, const ir_entity *ent1, const ir_entity *ent2, int backedge, ird_color_t color, const char *fmt, ...)
376
{
377
	va_list ap;
378

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

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

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

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

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

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

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

Michael Beck's avatar
Michael Beck committed
449
/*-----------------------------------------------------------------*/
450
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
451
/*-----------------------------------------------------------------*/
452

453
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
454

Michael Beck's avatar
Michael Beck committed
455
/*-----------------------------------------------------------------*/
456
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
457
/*-----------------------------------------------------------------*/
458

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

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

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

489
	return pmap_get(void, irdump_link_map, n);
490
491
}

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

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

510
	return pmap_get(void, irdump_link_map, irg);
511
512
}

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

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

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

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

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

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

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

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

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

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

628
629
630
	foreach_irp_irg_r(i, irg) {
		ird_set_irg_link(irg, NULL);
	}
631

632
	ird_walk_graph(irg, clear_link, collect_node, irg);
633

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

638
	return (ir_node**)ird_get_irg_link(irg);
639
640
}

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

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

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
653
654
655
656
657
658
	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)));
659
660
		break;

661
662
663
664
665
666
	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));
667
		break;
668
669

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

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

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

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

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

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

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

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

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

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

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

776
			for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
				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;
801
802
803
	case iro_Cmp:
		fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
		break;
804
	case iro_Confirm:
805
		fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
806
807
		break;
	case iro_CopyB:
808
		ir_fprintf(F, "(%+F)", get_CopyB_type(n));
809
810
811
		break;

	default:
812
		break;
813
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
814
815
}

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

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

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

	n = local ? local : node;

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

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

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