irdump.c 64.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
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
 * 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;

/**
 * Edge kinds.
 */
typedef enum {
	data_edge           = 0x01,   /**< A data edge between two basic blocks. */
	block_edge          = 0x02,   /**< An edge from a node to its basic block. */
	cf_edge             = 0x03,   /**< A regularly control flow edge. */
	exc_cf_edge         = 0x04,   /**< An exceptional control flow edge. */
	mem_edge            = 0x05,   /**< A memory edge. */
	dominator_edge      = 0x06,   /**< A dominator edge from a block to its immediate dominator. */
	node2type_edge      = 0x07,   /**< An edge from an IR node to a type. */

	ent_type_edge       = 0x11,   /**< An edge from an entity to its type. */
	ent_own_edge        = 0x12,   /**< An edge from an entity to its owner type. */
	ent_overwrites_edge = 0x13,   /**< An edge from an entity to the entity it overwrites. */
	ent_value_edge      = 0x14,   /**< An edge from an entity to its value entity. */
	ent_corr_edge       = 0x15,   /**< An edge from an entity to the member entity its initializes. */

	meth_par_edge       = 0x21,   /**< An edge from a method type to one of its parameter types. */
	meth_res_edge       = 0x22,   /**< An edge from a method type to one of its result types. */
	type_super_edge     = 0x23,   /**< An edge from a class type to its super/basis type. */
	union_edge          = 0x24,   /**< An edge from a union type to its member types. */
	ptr_pts_to_edge     = 0x25,   /**< An edge from a pointer type to its points-to type. */
	arr_elt_type_edge   = 0x26,   /**< An edge from an array type to its element type. */
	arr_ent_edge        = 0x27,   /**< An edge from a array type to its element entity. */
	type_member_edge    = 0x28,   /**< An edge from a compound type to its member entities. */

	/* additional flags */
	intra_edge          = 0,      /**< Intra edge flag: edge do not cross basic block boundaries */
	inter_edge          = 0x40,   /**< Inter edge flag: edge cross basic block boundaries */
	back_edge           = 0x80    /**< Backwards edge flag. */
} edge_kind;

/* 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" */

149
150
151
152
153
154
155
156
157
158
159
160
161
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"

162
/** Dump only irgs with names that start with this prefix. */
163
164
static ident *dump_file_filter_id = NULL;

165
166
167
168
169
170
171
static ir_dump_flags_t flags =
	ir_dump_flag_blocks_as_subgraphs |
	ir_dump_flag_keepalive_edges |
	ir_dump_flag_ld_names |
	ir_dump_flag_back_edges |
	ir_dump_flag_consts_local |
	ir_dump_flag_analysed_types |
Matthias Braun's avatar
Matthias Braun committed
172
173
	ir_dump_flag_entities_in_hierarchy |
	ir_dump_flag_number_label;
174

175
static ird_color_t overrule_nodecolor = ird_color_default_node;
176

177
/** The vcg node attribute hook. */
178
static dump_node_vcgattr_func dump_node_vcgattr_hook = NULL;
179
/** The vcg edge attribute hook. */
180
static dump_edge_vcgattr_func dump_edge_vcgattr_hook = NULL;
181
/** The vcg dump block edge hook */
182
static dump_node_edge_func dump_block_edge_hook = NULL;
183
/** The vcg dump node edge hook. */
184
static dump_node_edge_func dump_node_edge_hook = NULL;
185

186
void set_dump_node_edge_hook(dump_node_edge_func func)
187
{
188
	dump_node_edge_hook = func;
189
190
}

191
dump_node_edge_func get_dump_node_edge_hook(void)
192
{
193
	return dump_node_edge_hook;
194
195
}

196
void set_dump_block_edge_hook(dump_node_edge_func func)
197
{
198
	dump_block_edge_hook = func;
199
200
}

201
dump_node_edge_func get_dump_block_edge_hook(void)
202
{
203
	return dump_node_edge_hook;
204
205
}

206
void set_dump_node_vcgattr_hook(dump_node_vcgattr_func hook)
207
{
208
	dump_node_vcgattr_hook = hook;
209
}
210

211
void set_dump_edge_vcgattr_hook(dump_edge_vcgattr_func hook)
212
{
213
	dump_edge_vcgattr_hook = hook;
214
}
215

216
void ir_set_dump_flags(ir_dump_flags_t new_flags)
217
{
218
	flags = new_flags;
219
220
}

221
void ir_add_dump_flags(ir_dump_flags_t new_flags)
222
{
223
	flags |= new_flags;
224
225
}

226
void ir_remove_dump_flags(ir_dump_flags_t to_remove)
227
{
228
	flags &= ~to_remove;
Michael Beck's avatar
Michael Beck committed
229
230
}

231
ir_dump_flags_t ir_get_dump_flags(void)
232
{
233
	return flags;
234
235
}

236
237
/** Returns 0 if dump_out_edge_flag or dump_loop_information_flag
 * are set, else returns dump_const_local_flag.
238
 */
239
static bool get_opt_dump_const_local(void)
240
{
241
242
243
244
	return (flags & ir_dump_flag_out_edges)
		|| (flags & ir_dump_flag_loops)
		|| (flags & ir_dump_flag_consts_local)
		|| (flags & ir_dump_flag_iredges);
245
246
}

247
static char *dump_filter;
248

249
void ir_set_dump_filter(const char *new_filter)
250
{
251
	free(dump_filter);
252
	dump_filter = xstrdup(new_filter);
253
254
}

255
const char *ir_get_dump_filter(void)
256
{
257
	return dump_filter;
258
259
}

260
int ir_should_dump(const char *name)
261
{
262
	const char *f, *n;
263

264
265
266
267
268
269
270
271
272
	if (dump_filter == NULL || dump_filter[0] == '\0')
		return 1;

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

275
276
/* -------------- some extended helper functions ----------------- */

277
char const *get_mode_name_ex(ir_mode const *const mode)
278
{
279
280
	if (is_mode(mode))
		return get_mode_name(mode);
281
	return "<ERROR>";
282
283
}

284
285
286
287
288
#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
289
/** define a custom color. */
290
291
292
293
294
295
296
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;
297
	color_names[num] = (const char*)obstack_finish(&color_obst);
298
299
}

Michael Beck's avatar
Michael Beck committed
300
/** Define a named color. */
301
302
303
304
305
306
307
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
308
/** Initializes the used colors. */
309
310
static void init_colors(void)
{
311
	static bool initialized = 0;
Michael Beck's avatar
Michael Beck committed
312
	if (initialized)
313
314
315
316
317
318
319
320
321
322
323
324
325
		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");
326
	custom_color(ird_color_uses_memory,           "153 153 255");
327
328
329
	custom_color(ird_color_phi,                   "105 255 105");
	custom_color(ird_color_anchor,                "100 100 255");
	named_color(ird_color_error,                  "red");
330
	custom_color(ird_color_entity,                "204 204 255");
331
332
333
334

	initialized = 1;
}

335
/**
336
 * Prints the VCG color to a file.
337
 */
338
static void print_vcg_color(FILE *out, ird_color_t color)
339
{
340
	assert(color < ird_color_count);
341
	fprintf(out, "color:%s", color_names[color]);
342
343
}

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
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));
}

364
365
366
367
368
/**
 * Prints the edge kind of a given IR node.
 *
 * Projs should be dumped near their predecessor, so they get "nearedge".
 */
369
static void print_node_edge_kind(FILE *out, const ir_node *node)
370
{
371
	if (is_Proj(node)) {
372
		fprintf(out, "nearedge: ");
373
	} else {
374
		fprintf(out, "edge: ");
375
376
377
	}
}

Michael Beck's avatar
Michael Beck committed
378
/**
379
380
 * 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
381
 */
Michael Beck's avatar
Michael Beck committed
382
static void print_type_type_edge(FILE *F, const ir_type *S, const ir_type *T, const char *fmt, ...)
383
{
384
	va_list ap;
385

386
	va_start(ap, fmt);
387
388
389
390
	fprintf(F, "edge: { sourcename: ");
	print_typeid(F, S);
	fprintf(F, " targetname: ");
	print_typeid(F, T);
391
	ir_vfprintf(F, fmt, ap);
392
393
	fprintf(F,"}\n");
	va_end(ap);
394
395
}

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

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

Michael Beck's avatar
Michael Beck committed
414
/**
Michael Beck's avatar
Michael Beck committed
415
 * Prints the edge from an entity ent1 to an entity ent2 with additional info fmt, ...
416
 * to the file F.
Michael Beck's avatar
Michael Beck committed
417
 */
Michael Beck's avatar
Michael Beck committed
418
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, ...)
419
{
420
	va_list ap;
421

422
423
	va_start(ap, fmt);
	if (backedge)
424
		fprintf(F, "backedge: { sourcename: ");
425
	else
426
427
428
429
		fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent1);
	fprintf(F, " targetname: ");
	print_entityid(F, ent2);
430
	ir_vfprintf(F, fmt, ap);
431
	fprintf(F, " ");
432
	if (color != ird_color_none)
433
		print_vcg_color(F, color);
434
435
	fprintf(F, "}\n");
	va_end(ap);
436
437
}

Michael Beck's avatar
Michael Beck committed
438
/**
Michael Beck's avatar
Michael Beck committed
439
 * Prints the edge from an entity ent to a type tp with additional info fmt, ...
440
 * to the file F.
Michael Beck's avatar
Michael Beck committed
441
 */
Michael Beck's avatar
Michael Beck committed
442
static void print_ent_type_edge(FILE *F, const ir_entity *ent, const ir_type *tp, const char *fmt, ...)
443
{
444
	va_list ap;
445

446
	va_start(ap, fmt);
447
448
449
450
	fprintf(F, "edge: { sourcename: ");
	print_entityid(F, ent);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
451
	ir_vfprintf(F, fmt, ap);
452
453
	fprintf(F,"}\n");
	va_end(ap);
454
455
}

Michael Beck's avatar
Michael Beck committed
456
/**
Michael Beck's avatar
Michael Beck committed
457
 * Prints the edge from a node irn to a type tp with additional info fmt, ...
458
 * to the file F.
Michael Beck's avatar
Michael Beck committed
459
 */
Michael Beck's avatar
Michael Beck committed
460
static void print_node_type_edge(FILE *F, const ir_node *irn, ir_type *tp, const char *fmt, ...)
461
{
462
	va_list ap;
463

464
	va_start(ap, fmt);
465
466
467
468
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_typeid(F, tp);
469
	ir_vfprintf(F, fmt, ap);
470
471
	fprintf(F,"}\n");
	va_end(ap);
472
473
}

Michael Beck's avatar
Michael Beck committed
474
/**
Michael Beck's avatar
Michael Beck committed
475
 * Prints the edge from a node irn to an entity ent with additional info fmt, ...
476
 * to the file F.
Michael Beck's avatar
Michael Beck committed
477
 */
Michael Beck's avatar
Michael Beck committed
478
static void print_node_ent_edge(FILE *F, const ir_node *irn, const ir_entity *ent, const char *fmt, ...)
479
{
480
	va_list ap;
481

482
	va_start(ap, fmt);
483
484
485
486
	fprintf(F, "edge: { sourcename: ");
	print_nodeid(F, irn);
	fprintf(F, " targetname: ");
	print_entityid(F, ent);
487
	ir_vfprintf(F, fmt, ap);
488
489
	fprintf(F,"}\n");
	va_end(ap);
490
491
}

Michael Beck's avatar
Michael Beck committed
492
/*-----------------------------------------------------------------*/
493
/* global and ahead declarations                                   */
Michael Beck's avatar
Michael Beck committed
494
/*-----------------------------------------------------------------*/
495

496
static void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
497

Michael Beck's avatar
Michael Beck committed
498
/*-----------------------------------------------------------------*/
499
/* Helper functions.                                                */
Michael Beck's avatar
Michael Beck committed
500
/*-----------------------------------------------------------------*/
501

Michael Beck's avatar
Michael Beck committed
502
503
504
505
/**
 * This map is used as a private link attr to be able to call dumper
 * anywhere without destroying link fields.
 */
506
507
static pmap *irdump_link_map = NULL;

508
509
510
511
/** 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
512
 * initialization is performed lazily and not called from within init_firm.
513
 *
Michael Beck's avatar
Michael Beck committed
514
 * Creates the link attribute map. */
515
516
static void init_irdump(void)
{
517
518
519
520
521
	/* 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("");
522
}
523

Michael Beck's avatar
Michael Beck committed
524
525
526
/**
 * Returns the private link field.
 */
527
528
static void *ird_get_irn_link(const ir_node *n)
{
Michael Beck's avatar
Michael Beck committed
529
530
	if (irdump_link_map == NULL)
		return NULL;
531

532
	return pmap_get(void, irdump_link_map, n);
533
534
}

Michael Beck's avatar
Michael Beck committed
535
536
537
/**
 * Sets the private link field.
 */
538
539
static void ird_set_irn_link(const ir_node *n, void *x)
{
Michael Beck's avatar
Michael Beck committed
540
	if (irdump_link_map == NULL)
541
		init_irdump();
Michael Beck's avatar
Michael Beck committed
542
	pmap_insert(irdump_link_map, n, x);
543
544
}

Michael Beck's avatar
Michael Beck committed
545
546
547
/**
 * Gets the private link field of an irg.
 */
548
549
static void *ird_get_irg_link(const ir_graph *irg)
{
Michael Beck's avatar
Michael Beck committed
550
551
	if (irdump_link_map == NULL)
		return NULL;
552

553
	return pmap_get(void, irdump_link_map, irg);
554
555
}

Michael Beck's avatar
Michael Beck committed
556
557
558
/**
 * Sets the private link field of an irg.
 */
559
560
static void ird_set_irg_link(const ir_graph *irg, void *x)
{
Michael Beck's avatar
Michael Beck committed
561
562
563
	if (irdump_link_map == NULL)
		init_irdump();
	pmap_insert(irdump_link_map, irg, x);
564
565
}

Michael Beck's avatar
Michael Beck committed
566
/**
567
 * Walker, clears the private link field.
Michael Beck's avatar
Michael Beck committed
568
 */
569
570
static void clear_link(ir_node *node, void *env)
{
571
	(void) env;
572
	ird_set_irn_link(node, NULL);
573
574
}

Michael Beck's avatar
Michael Beck committed
575
/**
576
 * If the entity has a ld_name, returns it if the dump_ld_name is set,
577
 * else returns the name of the entity.
Michael Beck's avatar
Michael Beck committed
578
 */
579
static const char *get_ent_dump_name_(const ir_entity *ent, bool dump_ld_name)
580
{
Michael Beck's avatar
Michael Beck committed
581
	if (ent == NULL)
582
583
584
		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
585
586
		if (ent->ld_name != NULL)
			return get_id_str(ent->ld_name);
587
588
	}
	return get_id_str(ent->name);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
589
590
}

591
592
const char *get_ent_dump_name(const ir_entity *ent)
{
593
	return get_ent_dump_name_(ent, flags & ir_dump_flag_ld_names);
594
595
}

596
597
const char *get_irg_dump_name(const ir_graph *irg)
{
598
	/* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
599
	return get_ent_dump_name_(get_irg_entity(irg), true);
600
601
}

602
603
604
/**
 * Returns non-zero if a node is in floating state.
 */
605
606
static int node_floats(const ir_node *n)
{
607
	ir_graph *irg = get_irn_irg(n);
608
	return ((get_irn_pinned(n) == op_pin_state_floats) &&
609
	        (get_irg_pinned(irg) == op_pin_state_floats));
610
611
}

612
613
614
/**
 *  Walker that visits the anchors
 */
615
616
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
{
617
618
	if ((flags & ir_dump_flag_all_anchors)
			|| ((flags & ir_dump_flag_iredges) && edges_activated(irg))) {
Michael Beck's avatar
Michael Beck committed
619
		irg_walk_anchors(irg, pre, post, env);
620
621
	} else {
		irg_walk_graph(irg, pre, post, env);
622
	}
623
624
}

Michael Beck's avatar
Michael Beck committed
625
/**
626
 * Walker, allocates an array for all blocks and puts their non-floating
627
 * nodes into this array.
Michael Beck's avatar
Michael Beck committed
628
 */
629
630
static void collect_node(ir_node *node, void *env)
{
631
	(void) env;
632
633
	if (is_Block(node)
	    || node_floats(node)
634
	    || (get_op_flags(get_irn_op(node)) & irop_flag_dump_noblock)) {
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
		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);
		}
	}
653
654
655
656
}

/** Construct lists to walk ir block-wise.
 *
657
 * Collects all blocks, nodes not op_pin_state_pinned,
658
 * Bad, NoMem and Unknown into a flexible array in link field of
659
660
 * irg they belong to.  Sets the irg link field to NULL in all
 * graphs not visited.
Michael Beck's avatar
Michael Beck committed
661
662
 * Free the list with DEL_ARR_F().
 */
663
664
static ir_node **construct_block_lists(ir_graph *irg)
{
665
	size_t   i;
666
	int      walk_flag = ir_resources_reserved(irg) & IR_RESOURCE_IRN_VISITED;
667

668
	if (walk_flag) {
669
		ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
670
	}
671

672
673
	for (i = get_irp_n_irgs(); i > 0;)
		ird_set_irg_link(get_irp_irg(--i), NULL);
674

675
	ird_walk_graph(irg, clear_link, collect_node, irg);
676

Michael Beck's avatar
Michael Beck committed
677
	if (walk_flag) {
678
		ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
Matthias Braun's avatar
Matthias Braun committed
679
	}
680

681
	return (ir_node**)ird_get_irg_link(irg);
682
683
}

684
void dump_node_opcode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
685
{
686
687
688
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
689
690
691
692
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_opcode_txt);
		return;
	}
693
694
695

	/* implementation for default nodes */
	switch (get_irn_opcode(n)) {
696
	case iro_SymConst:
697
698
699
700
701
702
703
704
		switch (get_SymConst_kind(n)) {
		case symconst_addr_ent:
			fprintf(F, "SymC &%s", get_entity_name(get_SymConst_entity(n)));
			break;
		case symconst_ofs_ent:
			fprintf(F, "SymC %s offset", get_entity_name(get_SymConst_entity(n)));
			break;
		case symconst_type_size:
705
			ir_fprintf(F, "SymC %+F size", get_SymConst_type(n));
706
707
			break;
		case symconst_type_align:
708
			ir_fprintf(F, "SymC %+F align", get_SymConst_type(n));
709
710
			break;
		}
711
		break;
712
713

	case iro_Load:
714
		if (get_Load_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
715
			fprintf(F, "ua");
716
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n)));
717
		break;
Michael Beck's avatar
Michael Beck committed
718
	case iro_Store:
719
		if (get_Store_unaligned(n) == align_non_aligned)
Michael Beck's avatar
Michael Beck committed
720
721
722
			fprintf(F, "ua");
		fprintf(F, "%s", get_irn_opname(n));
		break;
723
	case iro_Block:
724
725
726
727
728
		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),
729
			(flags & ir_dump_flag_show_marks) ? (get_Block_mark(n) ? "*" : "") : "");
730
		break;
731
	case iro_Div:
732
		fprintf(F, "%s", get_irn_opname(n));
733
		if (get_Div_no_remainder(n))
734
			fprintf(F, "RL");
735
		fprintf(F, "[%s]", get_mode_name_ex(get_Div_resmode(n)));
736
737
		break;
	case iro_Mod:
738
		fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n)));
739
		break;
740
741
742
	case iro_Builtin:
		fprintf(F, "%s[%s]", get_irn_opname(n), get_builtin_kind_name(get_Builtin_kind(n)));
		break;
743
744
745

	default:
		fprintf(F, "%s", get_irn_opname(n));
746
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
747
748
}

Michael Beck's avatar
Michael Beck committed
749
750
751
752
/**
 * Dump the mode of a node n to a file F.
 * Ignore modes that are "always known".
 */
753
static void dump_node_mode(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
754
{
755
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));
756
	unsigned         iro;
Michael Beck's avatar
Michael Beck committed
757
	ir_mode         *mode;
758
759

	/* call the dump_node operation if available */
760
761
762
763
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_mode_txt);
		return;
	}
764
765
766
767
768
769
770
771
772
773
774
775
776

	/* default implementation */
	iro = get_irn_opcode(n);
	switch (iro) {
	case iro_SymConst:
	case iro_Sel:
	case iro_End:
	case iro_Return:
	case iro_Free:
	case iro_Sync:
	case iro_Jmp:
	case iro_NoMem:
		break;
Michael Beck's avatar
Michael Beck committed
777
778
	default:
		mode = get_irn_mode(n);
779

Michael Beck's avatar
Michael Beck committed
780
		if (mode != NULL && mode != mode_BB && mode != mode_ANY && mode != mode_BAD &&
781
			(mode != mode_T || iro == iro_Proj))
782
			fprintf(F, "%s", get_mode_name_ex(mode));
783
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
784
785
}

Michael Beck's avatar
Michael Beck committed
786
/**
787
 * Dump the type of a node n to a file F if it's known.
Michael Beck's avatar
Michael Beck committed
788
 */
789
static int dump_node_typeinfo(FILE *F, const ir_node *n)
790
{
791
	ir_graph *irg = get_irn_irg(n);
792
793
	int bad = 0;

794
	if (ir_get_dump_flags() & ir_dump_flag_analysed_types) {
795
796
		if (get_irg_typeinfo_state(irg) == ir_typeinfo_consistent  ||
			get_irg_typeinfo_state(irg) == ir_typeinfo_inconsistent) {
797
			ir_type *tp = get_irn_typeinfo_type(n);
Matthias Braun's avatar
Matthias Braun committed
798
			ir_fprintf(F, "[%+F]", tp);
799
800
801
		}
	}
	return bad;
802
803
}

Michael Beck's avatar
Michael Beck committed
804
/**
805
 * Dump additional node attributes of some nodes to a file F.
Michael Beck's avatar
Michael Beck committed
806
 */
807
static void dump_node_nodeattr(FILE *F, const ir_node *n)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
808
{
809
	ir_node *pred;
810
	unsigned code;
811
812
813
814
	long proj_nr;
	const ir_op_ops *ops = get_op_ops(get_irn_op(n));

	/* call the dump_node operation if available */
815
816
817
818
	if (ops->dump_node) {
		ops->dump_node(F, n, dump_node_nodeattr_txt);
		return;
	}
819
820

	switch (get_irn_opcode(n)) {
821
822
823
824
	case iro_Const:
		ir_fprintf(F, "%T ", get_Const_tarval(n));
		break;

825
826
827
828
829
	case iro_Proj:
		pred    = get_Proj_pred(n);
		proj_nr = get_Proj_proj(n);
		code    = get_irn_opcode(pred);

830
		if (code == iro_Proj && get_irn_opcode(get_Proj_pred(pred)) == iro_Start) {
831
			fprintf(F, "Arg %ld ", proj_nr);
832
		} else {
833
834
			unsigned i, j, f = 0;

835
			for (i = 0; i < ARRAY_SIZE(proj_lut); ++i) {
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
				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;
860
861
862
	case iro_Cmp:
		fprintf(F, "%s ", get_relation_string(get_Cmp_relation(n)));
		break;
863
	case iro_Confirm:
864
		fprintf(F, "%s ", get_relation_string(get_Confirm_relation(n)));
865
866
		break;
	case iro_CopyB:
867
		ir_fprintf(F, "(%+F)", get_CopyB_type(n));
868
869
870
		break;

	default:
871
		break;
872
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
873
874
}

875
void dump_node_label(FILE *F, const ir_node *n)
876
{
877
	dump_node_opcode(F, n);
878
	fputs(" ", F);
879
	dump_node_mode(F, n);
880
	fprintf(F, " ");
881
882
883
	dump_node_typeinfo(F, n);
	dump_node_nodeattr(F, n);
	if (flags & ir_dump_flag_number_label) {
884
885
		fprintf(F, "%ld", get_irn_node_nr(n));
	}
886
	if (flags & ir_dump_flag_idx_label) {
887
888
		fprintf(F, ":%u", get_irn_idx(n));
	}
889
890
}

Michael Beck's avatar
Michael Beck committed
891
/**
892
 * Dumps the attributes of a node n into the file F.
Michael Beck's avatar
Michael Beck committed
893
894
 * Currently this is only the color of a node.
 */
895
static void dump_node_vcgattr(FILE *F, const ir_node *node, const ir_node *local, bool bad)
Götz Lindenmaier's avatar
Götz Lindenmaier committed
896
{
897
	ir_mode *mode;
898
	const ir_node *n;
899
900

	if (bad) {
901
		print_vcg_color(F, ird_color_error);
902
903
904
		return;
	}