irdump.c 58.8 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

#include "irgwalk.h"
#include "tv_t.h"
28
#include "irouts_t.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
40

#include "array.h"
#include "pmap.h"
41
#include "obst.h"
42
#include "pset.h"
43
#include "util.h"
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
 * 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,
61
62
63
64
	ird_color_type,
	ird_color_edge_ent_type,
	ird_color_edge_type_member,
	ird_color_segment_type,
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
	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 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_CF_EDGE_ATTR  "class:20 priority:60 color:purple"
#define KEEP_ALIVE_DF_EDGE_ATTR  "class:20 priority:10 color:purple"
#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. */
93
#define ENT_TYPE_EDGE_ATTR       "class: 3 label: \"type\""
94
95
96
97
98
99
#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 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 ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
100
#define TYPE_MEMBER_EDGE_ATTR    "class: 12 label: \"member\""
101

102
typedef struct pns_lookup {
103
	unsigned    nr;     /**< the proj number */
104
105
106
107
108
109
110
111
112
113
114
	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"

115
116
117
118
119
120
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
121
122
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
123

124
static ird_color_t overrule_nodecolor = ird_color_default_node;
125

126
/** The vcg node attribute hook. */
127
static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
128
/** The vcg edge attribute hook. */
129
static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
130
/** The vcg dump block edge hook */
131
static dump_node_edge_func dump_block_edge_hook = NULL;
132
/** The vcg dump node edge hook. */
133
static dump_node_edge_func dump_node_edge_hook = NULL;
134

135
void set_dump_node_edge_hook(dump_node_edge_func func)
136
{
137
	dump_node_edge_hook = func;
138
139
}

140
dump_node_edge_func get_dump_node_edge_hook(void)
141
{
142
	return dump_node_edge_hook;
143
144
}

145
void set_dump_block_edge_hook(dump_node_edge_func func)
146
{
147
	dump_block_edge_hook = func;
148
149
}

150
dump_node_edge_func get_dump_block_edge_hook(void)
151
{
152
	return dump_node_edge_hook;
153
154
}

155
void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
156
{
157
	dump_node_vcgattr_hook = hook;
158
}
159

160
void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
161
{
162
	dump_edge_vcgattr_hook = hook;
163
}
164

165
void ir_set_dump_flags(ir_dump_flags_t new_flags)
166
{
167
	flags = new_flags;
168
169
}

170
void ir_add_dump_flags(ir_dump_flags_t new_flags)
171
{
172
	flags |= new_flags;
173
174
}

175
void ir_remove_dump_flags(ir_dump_flags_t to_remove)
176
{
177
	flags &= ~to_remove;
Michael Beck's avatar
Michael Beck committed
178
179
}

180
ir_dump_flags_t ir_get_dump_flags(void)
181
{
182
	return flags;
183
184
}

185
186
/** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
 * are set, else returns dump_const_local_flag.
187
 */
188
static bool get_opt_dump_const_local(void)
189
{
190
191
192
193
	return (flags & ir_dump_flag_out_edges)
		|| (flags & ir_dump_flag_loops)
		|| (flags & ir_dump_flag_consts_local)
		|| (flags & ir_dump_flag_iredges);
194
195
}

196
static char *dump_filter;
197

198
void ir_set_dump_filter(const char *new_filter)
199
{
200
	free(dump_filter);
201
	dump_filter = xstrdup(new_filter);
202
203
}

204
const char *ir_get_dump_filter(void)
205
{
206
	return dump_filter;
207
208
}

209
210
/** 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)
211
{
212
	if (!dump_filter)
213
214
		return 1;

215
	for (char const *n = name, *f = dump_filter; *f != '\0'; ++n, ++f) {
216
217
218
219
		if (*n != *f)
			return 0;
	}
	return 1;
220
221
}

222
223
/* -------------- some extended helper functions ----------------- */

224
225
226
227
228
#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
229
/** define a custom color. */
230
231
232
233
234
235
236
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;
237
	color_names[num] = (const char*)obstack_finish(&color_obst);
238
239
}

Michael Beck's avatar
Michael Beck committed
240
/** Define a named color. */
241
242
243
244
245
246
247
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
248
/** Initializes the used colors. */
249
250
static void init_colors(void)
{
Matthias Braun's avatar
Matthias Braun committed
251
	static bool initialized = false;
Michael Beck's avatar
Michael Beck committed
252
	if (initialized)
253
		return;
Matthias Braun's avatar
Matthias Braun committed
254
	initialized = true;
255
256
257

	obstack_init(&color_obst);

Matthias Braun's avatar
Matthias Braun committed
258
259
260
261
262
263
264
265
266
267
	// note: hsv values are in degree, [0,1], [0,1]
	custom_color(ird_color_prog_background,  "204 204 204"); //hsv   0,   0, .8
	custom_color(ird_color_block_background, "222 239 234"); //hsv 165, .05, .92
	custom_color(ird_color_default_node,     "242 242 242"); //hsv   0,   0, .95
	custom_color(ird_color_memory,           "153 153 255"); //hsv 240,  .4, 1.
	custom_color(ird_color_controlflow,      "255 153 153"); //hsv   0,  .4, 1.
	custom_color(ird_color_const,            "255 255 153"); //hsv  60,  .4, 1.
	custom_color(ird_color_phi,              "153 255 153"); //hsv 120,  .4, 1.
	custom_color(ird_color_anchor,           "255 153 255"); //hsv 300,  .4, 1.
	custom_color(ird_color_entity,           "127 127 127"); //hsv   0,   0, .5
268
269
270
271
	custom_color(ird_color_type,             "153 255 153"); //hsv 120,  .4, 1.
	custom_color(ird_color_segment_type,     "153 153 255"); //hsv 240,  .4, 1.
	named_color(ird_color_edge_type_member,  "darkgrey");
	named_color(ird_color_edge_ent_type,     "green");
272
273
	named_color(ird_color_block_inout,       "lightblue");
	named_color(ird_color_error,             "red");
274
275
}

276
/**
277
 * Prints the VCG color to a file.
278
 */
279
static void print_vcg_color(FILE *out, ird_color_t color)
280
{
281
	assert(color < ird_color_count);
282
	fprintf(out, "color:%s", color_names[color]);
283
284
}

285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
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));
}

305
306
307
308
309
/**
 * Prints the edge kind of a given IR node.
 *
 * Projs should be dumped near their predecessor, so they get "nearedge".
 */
310
static void print_node_edge_kind(FILE *out, const ir_node *node)
311
{
312
	if (is_Proj(node)) {
313
		fprintf(out, "nearedge: ");
314
	} else {
315
		fprintf(out, "edge: ");
316
317
318
	}
}

Michael Beck's avatar
Michael Beck committed
319
/**
320
321
 * 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
322
 */
Michael Beck's avatar
Michael Beck committed
323
static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
324
{
325
	va_list ap;
326

327
	va_start(ap, fmt);
328
329
330
331
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, S);
	fprintf(F, " targetname: ");
	print_typeid(F, T);
332
	ir_vfprintf(F, fmt, ap);
333
334
	fprintf(F,"}\n");
	va_end(ap);
335
336
}

Michael Beck's avatar
Michael Beck committed
337
/**
Michael Beck's avatar
Michael Beck committed
338
 * Prints the edge from a type tp to an entity ent with additional info fmt, ...
339
 * to the file F.
Michael Beck's avatar
Michael Beck committed
340
 */
Michael Beck's avatar
Michael Beck committed
341
static void print_type_ent_edge(FILE *F, const ir_type *tp, const ir_entity *ent, const char *fmt, ...)
342
{
343
	va_list ap;
344

345
	va_start(ap, fmt);
346
347
348
349
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, tp);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
350
	ir_vfprintf(F, fmt, ap);
351
352
	fputc(' ', F);
	print_vcg_color(F, ird_color_edge_type_member);
353
354
	fprintf(F, "}\n");
	va_end(ap);
355
356
}

Michael Beck's avatar
Michael Beck committed
357
/**
Michael Beck's avatar
Michael Beck committed
358
 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
359
 * to the file F.
Michael Beck's avatar
Michael Beck committed
360
 */
Michael Beck's avatar
Michael Beck committed
361
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, ...)
362
{
363
	va_list ap;
364

365
366
	va_start(ap, fmt);
	if (backedge)
367
		fprintf(F, "backedge: { sourcename: ");
368
	else
369
370
371
372
		fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent1);
	fprintf(F, " targetname: ");
	print_entityid(F, ent2);
373
	ir_vfprintf(F, fmt, ap);
374
	fprintf(F, " ");
375
	if (color != ird_color_none)
376
		print_vcg_color(F, color);
377
378
	fprintf(F, "}\n");
	va_end(ap);
379
380
}

Michael Beck's avatar
Michael Beck committed
381
/**
Michael Beck's avatar
Michael Beck committed
382
 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
383
 * to the file F.
Michael Beck's avatar
Michael Beck committed
384
 */
Michael Beck's avatar
Michael Beck committed
385
static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
386
{
387
	va_list ap;
388

389
	va_start(ap, fmt);
390
391
392
393
	fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
394
	ir_vfprintf(F, fmt, ap);
395
396
	fputc(' ', F);
	print_vcg_color(F, ird_color_edge_ent_type);
397
398
	fprintf(F,"}\n");
	va_end(ap);
399
400
}

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

409
	va_start(ap, fmt);
410
411
412
413
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
414
	ir_vfprintf(F, fmt, ap);
415
416
	fprintf(F,"}\n");
	va_end(ap);
417
418
}

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

427
	va_start(ap, fmt);
428
429
430
431
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
432
	ir_vfprintf(F, fmt, ap);
433
434
	fprintf(F,"}\n");
	va_end(ap);
435
436
}

Michael Beck's avatar
Michael Beck committed
437
/*-----------------------------------------------------------------*/
438
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
439
/*-----------------------------------------------------------------*/
440

441
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
442

Michael Beck's avatar
Michael Beck committed
443
/*-----------------------------------------------------------------*/
444
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
445
/*-----------------------------------------------------------------*/
446

Michael Beck's avatar
Michael Beck committed
447
448
449
450
/**
 * This map is used as a private link attr to be able to call dumper
 * anywhere without destroying link fields.
 */
451
452
static pmap *irdump_link_map = NULL;

453
454
455
456
/** 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
457
 * initialization is performed lazily and not called from within init_firm.
458
 *
Michael Beck's avatar
Michael Beck committed
459
 * Creates the link attribute map. */
460
461
static void init_irdump(void)
{
462
	/* We need a new, empty map. */
Matthias Braun's avatar
Matthias Braun committed
463
464
	if (irdump_link_map)
		pmap_destroy(irdump_link_map);
465
	irdump_link_map = pmap_create();
466
}
467

Michael Beck's avatar
Michael Beck committed
468
469
470
/**
 * Returns the private link field.
 */
471
472
static void *ird_get_irn_link(const ir_node *n)
{
Michael Beck's avatar
Michael Beck committed
473
474
	if (irdump_link_map == NULL)
		return NULL;
475

476
	return pmap_get(void, irdump_link_map, n);
477
478
}

Michael Beck's avatar
Michael Beck committed
479
480
481
/**
 * Sets the private link field.
 */
482
483
static void ird_set_irn_link(const ir_node *n, void *x)
{
Michael Beck's avatar
Michael Beck committed
484
	if (irdump_link_map == NULL)
485
		init_irdump();
Michael Beck's avatar
Michael Beck committed
486
	pmap_insert(irdump_link_map, n, x);
487
488
}

Michael Beck's avatar
Michael Beck committed
489
490
491
/**
 * Gets the private link field of an irg.
 */
492
493
static void *ird_get_irg_link(const ir_graph *irg)
{
Michael Beck's avatar
Michael Beck committed
494
495
	if (irdump_link_map == NULL)
		return NULL;
496

497
	return pmap_get(void, irdump_link_map, irg);
498
499
}

Michael Beck's avatar
Michael Beck committed
500
501
502
/**
 * Sets the private link field of an irg.
 */
503
504
static void ird_set_irg_link(const ir_graph *irg, void *x)
{
Michael Beck's avatar
Michael Beck committed
505
506
507
	if (irdump_link_map == NULL)
		init_irdump();
	pmap_insert(irdump_link_map, irg, x);
508
509
}

Michael Beck's avatar
Michael Beck committed
510
/**
511
 * Walker, clears the private link field.
Michael Beck's avatar
Michael Beck committed
512
 */
513
514
static void clear_link(ir_node *node, void *env)
{
Matthias Braun's avatar
cleanup    
Matthias Braun committed
515
	(void)env;
516
	ird_set_irn_link(node, NULL);
517
518
}

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

535
536
const char *get_ent_dump_name(const ir_entity *ent)
{
537
	return get_ent_dump_name_(ent, flags & ir_dump_flag_ld_names);
538
539
}

540
541
const char *get_irg_dump_name(const ir_graph *irg)
{
542
	/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
543
	return get_ent_dump_name_(get_irg_entity(irg), true);
544
545
}

546
547
548
/**
 * Returns non-zero if a node is in floating state.
 */
549
550
static int node_floats(const ir_node *n)
{
551
	ir_graph *irg = get_irn_irg(n);
Matthias Braun's avatar
Matthias Braun committed
552
	return !get_irn_pinned(n) && get_irg_pinned(irg) == op_pin_state_floats;
553
554
}

555
556
557
/**
 *  Walker that visits the anchors
 */
558
559
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
{
560
561
	if ((flags & ir_dump_flag_all_anchors)
			|| ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
Michael Beck's avatar
Michael Beck committed
562
		irg_walk_anchors(irg, pre, post, env);
563
564
	} else {
		irg_walk_graph(irg, pre, post, env);
565
	}
566
567
}

Michael Beck's avatar
Michael Beck committed
568
/**
569
 * Walker, allocates an array for all blocks and puts their non-floating
570
 * nodes into this array.
Michael Beck's avatar
Michael Beck committed
571
 */
572
573
static void collect_node(ir_node *node, void *env)
{
Matthias Braun's avatar
Matthias Braun committed
574
	(void)env;
575
576
	if (is_Block(node)
	    || node_floats(node)
577
	    || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
Matthias Braun's avatar
Matthias Braun committed
578
579
580
581
		ir_node **arr = (ir_node**) ird_get_irg_link(get_irn_irg(node));
		if (arr == NULL)
			arr = NEW_ARR_F(ir_node*, 0);
		ARR_APP1(ir_node*, arr, node);
582
583
		ird_set_irg_link(get_irn_irg(node), arr);    /* arr is an l-value, APP_ARR might change it! */
	} else {
Matthias Braun's avatar
Matthias Braun committed
584
		ir_node *block = get_nodes_block(node);
585
586
587

		if (is_Bad(block)) {
			/* this node is in a Bad block, so we must place it into the graph's list */
Matthias Braun's avatar
Matthias Braun committed
588
589
590
591
			ir_node **arr = (ir_node**) ird_get_irg_link(get_irn_irg(node));
			if (arr == NULL)
				arr = NEW_ARR_F(ir_node*, 0);
			ARR_APP1(ir_node*, arr, node);
592
593
594
595
596
597
			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);
		}
	}
598
599
600
601
}

/** Construct lists to walk ir block-wise.
 *
Matthias Braun's avatar
Matthias Braun committed
602
603
604
 * Collects all blocks, nodes not pinned, Bad, NoMem and Unknown into a
 * flexible array in link field of irg they belong to.  Sets the irg link field
 * to NULL in all graphs not visited.
Michael Beck's avatar
Michael Beck committed
605
606
 * Free the list with DEL_ARR_F().
 */
607
608
static ir_node **construct_block_lists(ir_graph *irg)
{
609
	int const walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
610

611
	if (walk_flag) {
612
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
613
	}
614

615
616
617
	foreach_irp_irg_r(i, irg) {
		ird_set_irg_link(irg, NULL);
	}
618

619
	ird_walk_graph(irg, clear_link, collect_node, irg);
620

Michael Beck's avatar
Michael Beck committed
621
	if (walk_flag) {
622
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
623
	}
624

625
	return (ir_node**)ird_get_irg_link(irg);
626
627
}

628
void dump_node_opcode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
629
{
630
	/* call the dump_node operation if available */
631
	ir_op_ops const *const ops = get_op_ops(get_irn_op(n));
Matthias Braun's avatar
Matthias Braun committed
632
	if (ops->dump_node != NULL) {
633
634
635
		ops->dump_node(F, n, dump_node_opcode_txt);
		return;
	}
636

637
	char const *const name = get_irn_opname(n);
638
639
	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
640
	case iro_Address:
641
		fprintf(F, "%s &%s", name, get_entity_name(get_Address_entity(n)));
642
643
		break;

644
	case iro_Align:
645
		ir_fprintf(F, "%s %+F", name, get_Align_type(n));
646
647
		break;

648
	case iro_Block: {
Christoph Mallon's avatar
Christoph Mallon committed
649
		ir_graph   *const irg    = get_irn_irg(n);
650
		char const *const prefix =
Christoph Mallon's avatar
Christoph Mallon committed
651
652
			n == get_irg_start_block(irg) ?  "Start " :
			n == get_irg_end_block(irg)   ?  "End "   :
653
654
655
656
			"";
		char const *const mark =
			flags & ir_dump_flag_show_marks && get_Block_mark(n) ? "*" : "";
		fprintf(F, "%s%s%s", prefix, name, mark);
657
		break;
658
659
	}

Christoph Mallon's avatar
Christoph Mallon committed
660
661
662
663
664
665
666
667
	case iro_Builtin:
		fprintf(F, "%s[%s]", name, get_builtin_kind_name(get_Builtin_kind(n)));
		break;

	case iro_Const:
		ir_fprintf(F, "%s %T", name, get_Const_tarval(n));
		break;

668
	case iro_Div:
669
		fprintf(F, "%s", name);
670
		if (get_Div_no_remainder(n))
671
			fprintf(F, "RL");
Christoph Mallon's avatar
Christoph Mallon committed
672
		fprintf(F, "[%s]", get_mode_name(get_Div_resmode(n)));
673
		break;
674

675
676
677
678
679
680
	case iro_Phi:
		fprintf(F, "%s", name);
		if (get_Phi_loop(n))
			fprintf(F, "[loop]");
		break;

Christoph Mallon's avatar
Christoph Mallon committed
681
682
683
684
685
686
	case iro_Load: {
		char const *const prefix = get_Load_unaligned(n) == align_non_aligned ? "ua" : "";
		fprintf(F, "%s%s[%s]", prefix, name, get_mode_name(get_Load_mode(n)));
		break;
	}

687
	case iro_Mod:
688
		fprintf(F, "%s[%s]", name, get_mode_name(get_Mod_resmode(n)));
689
		break;
690

Christoph Mallon's avatar
Christoph Mallon committed
691
692
693
694
695
696
	case iro_Offset:
		fprintf(F, "%s %s", name, get_entity_name(get_Offset_entity(n)));
		break;

	case iro_Size:
		ir_fprintf(F, "%s %+F", name, get_Size_type(n));
697
		break;
698

Christoph Mallon's avatar
Christoph Mallon committed
699
700
701
702
703
704
	case iro_Store: {
		char const *const prefix = get_Store_unaligned(n) == align_non_aligned ? "ua" : "";
		fprintf(F, "%s%s", prefix, name);
		break;
	}

705
	default:
706
707
		fprintf(F, "%s", name);
		break;
708
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
709
710
}

Michael Beck's avatar
Michael Beck committed
711
712
713
714
/**
 * Dump the mode of a node n to a file F.
 * Ignore modes that are "always known".
 */
715
static void dump_node_mode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
716
{
717
	/* call the dump_node operation if available */
Matthias Braun's avatar
Matthias Braun committed
718
719
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
	if (ops->dump_node != NULL) {
720
721
722
		ops->dump_node(F, n, dump_node_mode_txt);
		return;
	}
723
724

	/* default implementation */
725
726
727
728
	ir_mode *const mode = get_irn_mode(n);
	if ((mode != mode_ANY && mode != mode_BAD && mode != mode_BB && mode != mode_M && mode != mode_T && mode != mode_X) ||
	    is_Bad(n) || is_Proj(n))
		fprintf(F, "%s", get_mode_name(mode));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
729
730
}

Michael Beck's avatar
Michael Beck committed
731
/**
732
 * Dump additional node attributes of some nodes to a file F.
Michael Beck's avatar
Michael Beck committed
733
 */
734
static void dump_node_nodeattr(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
735
{
736
	/* call the dump_node operation if available */
Matthias Braun's avatar
Matthias Braun committed
737
738
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
	if (ops->dump_node != NULL) {
739
740
741
		ops->dump_node(F, n, dump_node_nodeattr_txt);
		return;
	}
742
743

	switch (get_irn_opcode(n)) {
Matthias Braun's avatar
Matthias Braun committed
744
745
	case iro_Proj: {
		ir_node *pred    = get_Proj_pred(n);
746
		unsigned proj_nr = get_Proj_num(n);
Matthias Braun's avatar
Matthias Braun committed
747
		unsigned code    = get_irn_opcode(pred);
748

749
		if (code == iro_Proj && is_Start(get_Proj_pred(pred))) {
750
			fprintf(F, "Arg %u ", proj_nr);
751
752
753
		} else if (code == iro_Switch && proj_nr != pn_Switch_default) {
			char            const       *sep   = "case ";
			ir_switch_table const *const table = get_Switch_table(pred);
yb9976's avatar
yb9976 committed
754
			for (size_t i = 0, n = ir_switch_table_get_n_entries(table); i < n; ++i) {
755
756
757
758
759
760
761
762
763
				ir_switch_table_entry const *const entry = ir_switch_table_get_entry_const(table, i);
				if (entry->pn != proj_nr)
					continue;
				ir_fprintf(F, "%s%T", sep, entry->min);
				if (entry->min != entry->max)
					ir_fprintf(F, "...%T", entry->max);
				sep = ", ";
			}
			fputc(' ', F);
764
		} else {
Matthias Braun's avatar
Matthias Braun committed
765
766
767
768
769
770
771
772
773
			bool found = false;
			for (unsigned i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
				if (code != proj_lut[i].code)
					continue;
				for (unsigned j = 0; j < proj_lut[i].num_data; ++j) {
					if (proj_nr != proj_lut[i].data[j].nr)
						continue;
					fprintf(F, "%s ", proj_lut[i].data[j].name);
					found = true;
774
775
					break;
				}
Matthias Braun's avatar
Matthias Braun committed
776
				break;
777
			}
Matthias Braun's avatar
Matthias Braun committed
778
			if (!found)
779
				fprintf(F, "%u ", proj_nr);
780
781
782
783
784
785
786
787
			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;
Matthias Braun's avatar
Matthias Braun committed
788
	}
789
790
	case iro_Member:
		fprintf(F, "%s ", get_ent_dump_name(get_Member_entity(n)));
791
		break;
792
793
794
	case iro_Cmp:
		fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
		break;
795
	case iro_Confirm:
796
		fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
797
798
		break;
	case iro_CopyB:
799
		ir_fprintf(F, "(%+F)", get_CopyB_type(n));
800
801
802
		break;

	default:
803
		break;
804
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
805
806
}

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

Michael Beck's avatar
Michael Beck committed
822
/**
823
 * Dumps the attributes of a node n into the file F.
Michael Beck's avatar
Michael Beck committed
824
825
 * Currently this is only the color of a node.
 */
826
static void dump_node_vcgattr(FILE *F, const ir_node *node, const ir_node *local)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
827
{
828
	if (dump_node_vcgattr_hook != NULL) {
829
830
		if (dump_node_vcgattr_hook(F, node, local) != 0)
			return;
831
	}
832

833
	if (overrule_nodecolor != ird_color_default_node) {
834
835
836
837
		print_vcg_color(F, overrule_nodecolor);
		return;
	}

Matthias Braun's avatar
Matthias Braun committed
838
839
	const ir_node *n    = local ? local : node;
	ir_mode       *mode = get_irn_mode(n);
840
	if (mode == mode_M) {
841
842
843
844
		print_vcg_color(F, ird_color_memory);
		return;
	}

845
846
847
	switch (get_irn_opcode(n)) {
	case iro_Start:
	case iro_End:
Matthias Braun's avatar