irdump.c 60.4 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
/**
 * 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_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" */

113
114
115
116
117
118
119
120
121
122
123
124
125
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"

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

129
130
131
132
133
134
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
135
136
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
137

138
static ird_color_t overrule_nodecolor = ird_color_default_node;
139

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

149
void set_dump_node_edge_hook(dump_node_edge_func func)
150
{
151
	dump_node_edge_hook = func;
152
153
}

154
dump_node_edge_func get_dump_node_edge_hook(void)
155
{
156
	return dump_node_edge_hook;
157
158
}

159
void set_dump_block_edge_hook(dump_node_edge_func func)
160
{
161
	dump_block_edge_hook = func;
162
163
}

164
dump_node_edge_func get_dump_block_edge_hook(void)
165
{
166
	return dump_node_edge_hook;
167
168
}

169
void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
170
{
171
	dump_node_vcgattr_hook = hook;
172
}
173

174
void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
175
{
176
	dump_edge_vcgattr_hook = hook;
177
}
178

179
void ir_set_dump_flags(ir_dump_flags_t new_flags)
180
{
181
	flags = new_flags;
182
183
}

184
void ir_add_dump_flags(ir_dump_flags_t new_flags)
185
{
186
	flags |= new_flags;
187
188
}

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

194
ir_dump_flags_t ir_get_dump_flags(void)
195
{
196
	return flags;
197
198
}

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

210
static char *dump_filter;
211

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

218
const char *ir_get_dump_filter(void)
219
{
220
	return dump_filter;
221
222
}

223
224
/** 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)
225
{
226
	if (!dump_filter)
227
228
		return 1;

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

236
237
/* -------------- some extended helper functions ----------------- */

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

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

	obstack_init(&color_obst);

271
272
273
274
275
276
277
278
279
280
281
	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_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");
282
283
284
285

	initialized = 1;
}

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

295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
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));
}

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

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

337
	va_start(ap, fmt);
338
339
340
341
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, S);
	fprintf(F, " targetname: ");
	print_typeid(F, T);
342
	ir_vfprintf(F, fmt, ap);
343
344
	fprintf(F,"}\n");
	va_end(ap);
345
346
}

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

355
	va_start(ap, fmt);
356
357
358
359
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, tp);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
360
	ir_vfprintf(F, fmt, ap);
361
362
	fprintf(F, "}\n");
	va_end(ap);
363
364
}

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

373
374
	va_start(ap, fmt);
	if (backedge)
375
		fprintf(F, "backedge: { sourcename: ");
376
	else
377
378
379
380
		fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent1);
	fprintf(F, " targetname: ");
	print_entityid(F, ent2);
381
	ir_vfprintf(F, fmt, ap);
382
	fprintf(F, " ");
383
	if (color != ird_color_none)
384
		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);
398
399
400
401
	fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
402
	ir_vfprintf(F, fmt, ap);
403
404
	fprintf(F,"}\n");
	va_end(ap);
405
406
}

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

415
	va_start(ap, fmt);
416
417
418
419
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
420
	ir_vfprintf(F, fmt, ap);
421
422
	fprintf(F,"}\n");
	va_end(ap);
423
424
}

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

433
	va_start(ap, fmt);
434
435
436
437
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
438
	ir_vfprintf(F, fmt, ap);
439
440
	fprintf(F,"}\n");
	va_end(ap);
441
442
}

Michael Beck's avatar
Michael Beck committed
443
/*-----------------------------------------------------------------*/
444
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
445
/*-----------------------------------------------------------------*/
446

447
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
448

Michael Beck's avatar
Michael Beck committed
449
/*-----------------------------------------------------------------*/
450
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
451
/*-----------------------------------------------------------------*/
452

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

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

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

483
	return pmap_get(void, irdump_link_map, n);
484
485
}

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

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

504
	return pmap_get(void, irdump_link_map, irg);
505
506
}

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

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

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

542
543
const char *get_ent_dump_name(const ir_entity *ent)
{
544
	return get_ent_dump_name_(ent, flags & ir_dump_flag_ld_names);
545
546
}

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

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

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

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

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

618
	if (walk_flag) {
619
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
620
	}
621

622
623
624
	foreach_irp_irg_r(i, irg) {
		ird_set_irg_link(irg, NULL);
	}
625

626
	ird_walk_graph(irg, clear_link, collect_node, irg);
627

Michael Beck's avatar
Michael Beck committed
628
	if (walk_flag) {
629
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
630
	}
631

632
	return (ir_node**)ird_get_irg_link(irg);
633
634
}

635
void dump_node_opcode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
636
{
637
638
639
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
640
641
642
643
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_opcode_txt);
		return;
	}
644
645
646

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
647
648
649
650
651
652
	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)));
653
654
		break;

655
656
657
658
659
660
	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));
661
		break;
662
663

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

	default:
		fprintf(F, "%s", get_irn_opname(n));
696
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
697
698
}

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

	/* call the dump_node operation if available */
710
711
712
713
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_mode_txt);
		return;
	}
714
715
716
717

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

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

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

	/* call the dump_node operation if available */
750
751
752
753
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_nodeattr_txt);
		return;
	}
754
755

	switch (get_irn_opcode(n)) {
756
757
758
759
	case iro_Const:
		ir_fprintf(F, "%T ", get_Const_tarval(n));
		break;

760
761
762
763
764
	case iro_Proj:
		pred    = get_Proj_pred(n);
		proj_nr = get_Proj_proj(n);
		code    = get_irn_opcode(pred);

765
		if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start) {
766
			fprintf(F, "Arg %ld ", proj_nr);
767
		} else {
768
769
			unsigned i, j, f = 0;

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

	default:
806
		break;
807
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
808
809
}

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

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

834
	if (dump_node_vcgattr_hook != NULL) {
835
836
		if (dump_node_vcgattr_hook(F, node, local) != 0)
			return;
837
	}
838
839
840

	n = local ? local : node;

841
	if (overrule_nodecolor != ird_color_default_node) {
842
843
844
845
		print_vcg_color(F, overrule_nodecolor);
		return;
	}

846
	mode = get_irn_mode(n);
847
	if (mode == mode_M) {
848
849
850
851
		print_vcg_color(F, ird_color_memory);
		return;
	}

852
853
854
	switch (get_irn_opcode(n)) {
	case iro_Start:
	case iro_End:
855
		print_vcg_color(F, ird_color_anchor);
856
		return;
857
858
	case iro_Bad:
		print_vcg_color(F, ird_color_error);
859
		return;
860
	case iro_Block:
861
		print_vcg_color(F, ird_color_block_background);
862
		return;
863
	case iro_Phi:
864
		print_vcg_color(F, ird_color_phi);
865
866
		return;
	default:
867
		break;
868
	}
869
870
871
872
873
874
875
876
877
878
879
880
881
882

	if (mode == mode_X) {
		print_vcg_color(F, ird_color_controlflow);
		return;
	}

	ir_op *op = get_irn_op(n);

	if (is_op_constlike(op)) {
		print_vcg_color(F, ird_color_const);
	} else if (is_op_uses_memory(op)) {
		print_vcg_color(F, ird_color_memory);
	} else if (is_op_cfopcode(op) || is_op_forking(op)) {
		print_vcg_color(F, ird_color_controlflow);
883
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
884
885
}