irio.c 46.2 KB
Newer Older
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

/**
 * @file
 * @brief   Write textual representation of firm to file.
 * @author  Moritz Kroll
 * @version $Id$
 */
#include "config.h"

#include <string.h>
29
30
31
#include <ctype.h>
#include <stdbool.h>
#include <stdarg.h>
32
33
34

#include "irio.h"

35
#include "irnode_t.h"
36
37
#include "irprog.h"
#include "irgraph_t.h"
Michael Beck's avatar
Michael Beck committed
38
#include "irprintf.h"
39
40
41
42
43
44
45
#include "ircons.h"
#include "irgmod.h"
#include "irflag_t.h"
#include "irgwalk.h"
#include "tv.h"
#include "array.h"
#include "error.h"
46
#include "typerep.h"
47
#include "adt/set.h"
48
#include "adt/obst.h"
49

50
#define SYMERROR ((unsigned) ~0)
51

Moritz Kroll's avatar
Moritz Kroll committed
52
typedef struct io_env_t
53
{
54
	int c;                /**< currently read char */
55
	FILE *file;
56
	set *idset;           /**< id_entry set, which maps from file ids to new Firm elements */
57
	int ignoreblocks;
58
59
	const char *inputname;
	int line;
60
	ir_type **fixedtypes;
61
	struct obstack obst;
62
	ir_graph *irg;
63
64
65
66
67
68
} io_env_t;

typedef enum typetag_t
{
	tt_align,
	tt_allocation,
69
	tt_builtin,
70
	tt_cond_jmp_predicate,
71
72
	tt_initializer,
	tt_iro,
73
	tt_keyword,
74
	tt_mode_sort,
75
	tt_mode_arithmetic,
76
	tt_pin_state,
77
	tt_tpo,
78
	tt_type_state,
79
	tt_volatility,
Matthias Braun's avatar
Matthias Braun committed
80
	tt_linkage,
81
82
	tt_segment,
	tt_visibility
83
84
} typetag_t;

85
86
87
88
89
typedef enum keyword_t
{
	kw_constirg,
	kw_entity,
	kw_irg,
90
91
	kw_mode,
	kw_modes,
92
	kw_type,
93
94
95
	kw_typegraph,
	kw_program,
	kw_segment_type
96
97
} keyword_t;

98
typedef struct symbol_t
99
{
100
101
102
103
	const char *str;      /**< The name of this symbol. */
	typetag_t   typetag;  /**< The type tag of this symbol. */
	unsigned    code;     /**< The value of this symbol. */
} symbol_t;
104
105
106
107
108
109
110

typedef struct id_entry
{
	long id;
	void *elem;
} id_entry;

111
112
/** The symbol table, a set of symbol_t elements. */
static set *symtbl;
113

114
115
116
117
/**
 * Compare two symbol table entries.
 */
static int symbol_cmp(const void *elt, const void *key, size_t size)
118
{
119
	int res;
120
121
	const symbol_t *entry = (const symbol_t *) elt;
	const symbol_t *keyentry = (const symbol_t *) key;
122
	(void) size;
123
	res = entry->typetag - keyentry->typetag;
Michael Beck's avatar
Michael Beck committed
124
	if (res) return res;
125
126
127
128
129
130
131
132
133
134
135
	return strcmp(entry->str, keyentry->str);
}

static int id_cmp(const void *elt, const void *key, size_t size)
{
	const id_entry *entry = (const id_entry *) elt;
	const id_entry *keyentry = (const id_entry *) key;
	(void) size;
	return entry->id - keyentry->id;
}

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
static void __attribute__((format(printf, 2, 3)))
parse_error(io_env_t *env, const char *fmt, ...)
{
	va_list ap;
	int     line = env->line;

	/* workaround read_c "feature" that a '\n' triggers the line++
	 * instead of the character after the '\n' */
	if (env->c == '\n') {
		line--;
	}

	fprintf(stderr, "%s:%d: error ", env->inputname, line);

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
}

155
156
/** Initializes the symbol table. May be called more than once without problems. */
static void symtbl_init(void)
157
{
158
	symbol_t key;
159
160

	/* Only initialize once */
Michael Beck's avatar
Michael Beck committed
161
	if (symtbl != NULL)
162
		return;
163

164
	symtbl = new_set(symbol_cmp, 256);
165

166
#define INSERT(tt, s, cod)                                       \
167
168
169
	key.str = (s);                                               \
	key.typetag = (tt);                                          \
	key.code = (cod);                                            \
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
	set_insert(symtbl, &key, sizeof(key), firm_fnv_hash_str(s) + tt * 17)

#define INSERTENUM(tt, e) INSERT(tt, #e, e)
#define INSERTKEYWORD(k) INSERT(tt_keyword, #k, kw_##k)

	INSERT(tt_tpo, "array", tpo_array);
	INSERT(tt_tpo, "class", tpo_class);
	INSERT(tt_tpo, "method", tpo_method);
	INSERT(tt_tpo, "pointer", tpo_pointer);
	INSERT(tt_tpo, "primitive", tpo_primitive);
	INSERT(tt_tpo, "struct", tpo_struct);
	INSERT(tt_tpo, "union", tpo_union);
	INSERT(tt_tpo, "Unknown", tpo_unknown);

	INSERT(tt_mode_sort, "auxiliary", irms_auxiliary);
	INSERT(tt_mode_sort, "control_flow", irms_control_flow);
	INSERT(tt_mode_sort, "memory", irms_memory);
	INSERT(tt_mode_sort, "internal_boolean", irms_internal_boolean);
	INSERT(tt_mode_sort, "reference", irms_reference);
	INSERT(tt_mode_sort, "int_number", irms_int_number);
	INSERT(tt_mode_sort, "float_number", irms_float_number);

	INSERT(tt_segment, "global", IR_SEGMENT_GLOBAL);
	INSERT(tt_segment, "thread_local", IR_SEGMENT_THREAD_LOCAL);
	INSERT(tt_segment, "constructors", IR_SEGMENT_CONSTRUCTORS);
	INSERT(tt_segment, "destructors", IR_SEGMENT_DESTRUCTORS);
196

Matthias Braun's avatar
Matthias Braun committed
197
198
199
200
201
202
	INSERT(tt_linkage, "constant", IR_LINKAGE_CONSTANT);
	INSERT(tt_linkage, "weak", IR_LINKAGE_WEAK);
	INSERT(tt_linkage, "garbage_collect", IR_LINKAGE_GARBAGE_COLLECT);
	INSERT(tt_linkage, "merge", IR_LINKAGE_MERGE);
	INSERT(tt_linkage, "hidden_user", IR_LINKAGE_HIDDEN_USER);

203
204
205
	INSERT(tt_visibility, "local", ir_visibility_local);
	INSERT(tt_visibility, "external", ir_visibility_external);
	INSERT(tt_visibility, "default", ir_visibility_default);
206
	INSERT(tt_visibility, "private", ir_visibility_private);
207

208
209
210
	INSERTKEYWORD(constirg);
	INSERTKEYWORD(entity);
	INSERTKEYWORD(irg);
211
212
	INSERTKEYWORD(mode);
	INSERTKEYWORD(modes);
213
214
	INSERTKEYWORD(type);
	INSERTKEYWORD(typegraph);
215
216
	INSERTKEYWORD(program);
	INSERTKEYWORD(segment_type);
217

218
219
220
221
222
#include "gen_irio_lex.inl"

	INSERTENUM(tt_align, align_non_aligned);
	INSERTENUM(tt_align, align_is_aligned);

223
224
225
	INSERTENUM(tt_builtin, ir_bk_trap);
	INSERTENUM(tt_builtin, ir_bk_debugbreak);
	INSERTENUM(tt_builtin, ir_bk_return_address);
226
	INSERTENUM(tt_builtin, ir_bk_frame_address);
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
	INSERTENUM(tt_builtin, ir_bk_prefetch);
	INSERTENUM(tt_builtin, ir_bk_ffs);
	INSERTENUM(tt_builtin, ir_bk_clz);
	INSERTENUM(tt_builtin, ir_bk_ctz);
	INSERTENUM(tt_builtin, ir_bk_popcount);
	INSERTENUM(tt_builtin, ir_bk_parity);
	INSERTENUM(tt_builtin, ir_bk_bswap);
	INSERTENUM(tt_builtin, ir_bk_inport);
	INSERTENUM(tt_builtin, ir_bk_outport);
	INSERTENUM(tt_builtin, ir_bk_inner_trampoline);

	INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_NONE);
	INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_TRUE);
	INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_FALSE);

	INSERTENUM(tt_initializer, IR_INITIALIZER_CONST);
	INSERTENUM(tt_initializer, IR_INITIALIZER_TARVAL);
	INSERTENUM(tt_initializer, IR_INITIALIZER_NULL);
	INSERTENUM(tt_initializer, IR_INITIALIZER_COMPOUND);

247
248
249
250
251
252
253
254
	INSERTENUM(tt_mode_arithmetic, irma_uninitialized);
	INSERTENUM(tt_mode_arithmetic, irma_none);
	INSERTENUM(tt_mode_arithmetic, irma_twos_complement);
	INSERTENUM(tt_mode_arithmetic, irma_ones_complement);
	INSERTENUM(tt_mode_arithmetic, irma_int_BCD);
	INSERTENUM(tt_mode_arithmetic, irma_ieee754);
	INSERTENUM(tt_mode_arithmetic, irma_float_BCD);

255
256
257
258
259
260
261
262
263
264
265
	INSERTENUM(tt_pin_state, op_pin_state_floats);
	INSERTENUM(tt_pin_state, op_pin_state_pinned);
	INSERTENUM(tt_pin_state, op_pin_state_exc_pinned);
	INSERTENUM(tt_pin_state, op_pin_state_mem_pinned);

	INSERTENUM(tt_type_state, layout_undefined);
	INSERTENUM(tt_type_state, layout_fixed);

	INSERTENUM(tt_volatility, volatility_non_volatile);
	INSERTENUM(tt_volatility, volatility_is_volatile);

266
#undef INSERTKEYWORD
267
268
269
270
#undef INSERTENUM
#undef INSERT
}

271
272
273
274
275
276
277
278
279
280
281
static const char *get_segment_name(ir_segment_t segment)
{
	switch (segment) {
	case IR_SEGMENT_GLOBAL:       return "global";
	case IR_SEGMENT_THREAD_LOCAL: return "thread_local";
	case IR_SEGMENT_CONSTRUCTORS: return "constructors";
	case IR_SEGMENT_DESTRUCTORS:  return "destructors";
	}
	return "INVALID_SEGMENT";
}

282
283
284
285
286
287
288
289
290
291
292
static const char *get_visibility_name(ir_visibility visibility)
{
	switch (visibility) {
	case ir_visibility_local:    return "local";
	case ir_visibility_external: return "external";
	case ir_visibility_default:  return "default";
	case ir_visibility_private:  return "private";
	}
	return "INVALID_VISIBILITY";
}

293
294
/** Returns the according symbol value for the given string and tag, or SYMERROR if none was found. */
static unsigned symbol(const char *str, typetag_t typetag)
295
{
296
	symbol_t key, *entry;
297
298

	key.str = str;
299
	key.typetag = typetag;
300

301
	entry = (symbol_t*)set_find(symtbl, &key, sizeof(key), firm_fnv_hash_str(str) + typetag * 17);
302
	return entry ? entry->code : SYMERROR;
303
304
305
306
307
308
309
}

static void *get_id(io_env_t *env, long id)
{
	id_entry key, *entry;
	key.id = id;

310
	entry = (id_entry*)set_find(env->idset, &key, sizeof(key), (unsigned) id);
311
312
313
314
315
316
317
318
319
320
321
	return entry ? entry->elem : NULL;
}

static void set_id(io_env_t *env, long id, void *elem)
{
	id_entry key;
	key.id = id;
	key.elem = elem;
	set_insert(env->idset, &key, sizeof(key), (unsigned) id);
}

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
static void write_long(io_env_t *env, long value)
{
	fprintf(env->file, "%ld ", value);
}

static void write_int(io_env_t *env, int value)
{
	fprintf(env->file, "%d ", value);
}

static void write_unsigned(io_env_t *env, unsigned value)
{
	fprintf(env->file, "%u ", value);
}

static void write_entity_ref(io_env_t *env, ir_entity *entity)
{
	write_long(env, get_entity_nr(entity));
}

static void write_type_ref(io_env_t *env, ir_type *type)
{
	write_long(env, get_type_nr(type));
}

Matthias Braun's avatar
Matthias Braun committed
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
static void write_string(io_env_t *env, const char *string)
{
	const char *c;
	fputc('"', env->file);
	for (c = string; *c != '\0'; ++c) {
		switch (*c) {
		case '\n':
			fputc('\\', env->file);
			fputc('n', env->file);
			break;
		case '"':
		case '\\':
			fputc('\\', env->file);
			/* FALLTHROUGH */
		default:
			fputc(*c, env->file);
			break;
		}
	}
	fputc('"', env->file);
}

static void write_ident(io_env_t *env, ident *id)
{
	write_string(env, get_id_str(id));
	fputc(' ', env->file);
}

static void write_ident_null(io_env_t *env, ident *id)
{
	if (id == NULL) {
		fputs("NULL ", env->file);
	} else {
		write_ident(env, id);
	}
}

384
385
386
387
388
389
static void write_mode(io_env_t *env, ir_mode *mode)
{
	fputs(get_mode_name(mode), env->file);
	fputc(' ', env->file);
}

Matthias Braun's avatar
Matthias Braun committed
390
static void write_tarval(io_env_t *env, ir_tarval *tv)
391
392
393
394
395
396
397
398
{
	char buf[1024];
	write_mode(env, get_tarval_mode(tv));
	tarval_snprintf(buf, sizeof(buf), tv);
	fputs(buf, env->file);
	fputc(' ', env->file);
}

399
400
401
402
static void write_align(io_env_t *env, ir_node *irn)
{
	ir_align align;

Michael Beck's avatar
Michael Beck committed
403
404
405
406
407
408
	if (is_Load(irn))
		align = get_Load_align(irn);
	else if (is_Store(irn))
		align = get_Store_align(irn);
	else
		panic("Invalid optype for write_align");
409
410
411
412
413

	fputs(get_align_name(align), env->file);
	fputc(' ', env->file);
}

414
415
416
417
418
419
static void write_builtin_kind(io_env_t *env, ir_node *irn)
{
	fputs(get_builtin_kind_name(get_Builtin_kind(irn)), env->file);
	fputc(' ', env->file);
}

420
421
422
423
424
425
static void write_cond_jmp_predicate(io_env_t *env, ir_node *irn)
{
	fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(irn)), env->file);
	fputc(' ', env->file);
}

426
427
428
429
430
431
432
433
434
435
static void write_list_begin(io_env_t *env)
{
	fputs("[", env->file);
}

static void write_list_end(io_env_t *env)
{
	fputs("] ", env->file);
}

436
437
438
439
static void write_initializer(io_env_t *env, ir_initializer_t *ini)
{
	FILE *f = env->file;
	ir_initializer_kind_t ini_kind = get_initializer_kind(ini);
440

441
442
443
	fputs(get_initializer_kind_name(ini_kind), f);
	fputc(' ', f);

444
445
	switch (ini_kind) {
	case IR_INITIALIZER_CONST:
446
		write_long(env, get_irn_node_nr(get_initializer_const_value(ini)));
447
		break;
448

449
450
451
	case IR_INITIALIZER_TARVAL:
		write_tarval(env, get_initializer_tarval_value(ini));
		break;
452

453
454
	case IR_INITIALIZER_NULL:
		break;
455

456
457
	case IR_INITIALIZER_COMPOUND: {
		unsigned i, n = get_initializer_compound_n_entries(ini);
458
		fprintf(f, "%u ", n);
459
460
461
462
		for (i = 0; i < n; i++)
			write_initializer(env, get_initializer_compound_value(ini, i));
		break;
	}
463

464
465
	default:
		panic("Unknown initializer kind");
466
467
468
	}
}

469
470
471
472
473
474
475
476
477
478
static void write_pin_state(io_env_t *env, ir_node *irn)
{
	fputs(get_op_pin_state_name(get_irn_pinned(irn)), env->file);
	fputc(' ', env->file);
}

static void write_volatility(io_env_t *env, ir_node *irn)
{
	ir_volatility vol;

Michael Beck's avatar
Michael Beck committed
479
480
481
482
483
484
	if (is_Load(irn))
		vol = get_Load_volatility(irn);
	else if (is_Store(irn))
		vol = get_Store_volatility(irn);
	else
		panic("Invalid optype for write_volatility");
485
486
487
488
489

	fputs(get_volatility_name(vol), env->file);
	fputc(' ', env->file);
}

490
static void export_type_common(io_env_t *env, ir_type *tp)
491
{
492
	fprintf(env->file, "\ttype %ld %s %u %u %s %u ",
493
494
495
496
497
498
499
500
	        get_type_nr(tp),
	        get_type_tpop_name(tp),
	        get_type_size_bytes(tp),
	        get_type_alignment_bytes(tp),
	        get_type_state_name(get_type_state(tp)),
	        tp->flags);
}

501
502
503
504
static void export_type_pre(io_env_t *env, ir_type *tp)
{
	FILE *f = env->file;

Michael Beck's avatar
Michael Beck committed
505
	/* skip types to be handled by post walker */
506
507
508
509
510
511
512
	switch (get_type_tpop_code(tp)) {
	case tpo_array:
	case tpo_method:
	case tpo_pointer:
		return;
	default:
		break;
513
514
515
516
	}

	export_type_common(env, tp);

517
518
519
520
521
	switch (get_type_tpop_code(tp)) {
	case tpo_uninitialized:
		panic("invalid type found");

	case tpo_class:
Matthias Braun's avatar
Matthias Braun committed
522
		write_ident_null(env, get_compound_ident(tp));
523
524
525
526
527
528
529
530
531
		break;

	case tpo_primitive:
		write_mode(env, get_type_mode(tp));
		break;

	case tpo_union:
	case tpo_struct:
	case tpo_enumeration:
Matthias Braun's avatar
Matthias Braun committed
532
		write_ident_null(env, get_compound_ident(tp));
533
534
535
536
537
538
539
540
541
		break;

	case tpo_array:
	case tpo_method:
	case tpo_pointer:
	case tpo_code:
	case tpo_none:
	case tpo_unknown:
		break;
542
543
544
545
546
547
548
	}
	fputc('\n', f);
}

static void export_type_post(io_env_t *env, ir_type *tp)
{
	FILE *f = env->file;
Michael Beck's avatar
Michael Beck committed
549
	size_t i;
550

Michael Beck's avatar
Michael Beck committed
551
	/* skip types already handled by pre walker */
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	switch (get_type_tpop_code(tp)) {
	case tpo_class:
	case tpo_primitive:
	case tpo_struct:
	case tpo_union:
	case tpo_unknown:
	case tpo_uninitialized:
	case tpo_code:
	case tpo_none:
		return;
	case tpo_array:
	case tpo_method:
	case tpo_pointer:
	case tpo_enumeration:
		break;
567
568
569
	}

	export_type_common(env, tp);
570

571
572
	switch (get_type_tpop_code(tp)) {
	case tpo_array: {
Michael Beck's avatar
Michael Beck committed
573
574
		size_t n = get_array_n_dimensions(tp);
		ir_fprintf(f, "%zu %ld ", n, get_type_nr(get_array_element_type(tp)));
575
576
577
578
579
		for (i = 0; i < n; i++) {
			ir_node *lower = get_array_lower_bound(tp, i);
			ir_node *upper = get_array_upper_bound(tp, i);

			if (is_Const(lower))
580
				write_long(env, get_tarval_long(get_Const_tarval(lower)));
581
582
583
584
			else
				panic("Lower array bound is not constant");

			if (is_Const(upper))
585
				write_long(env, get_tarval_long(get_Const_tarval(upper)));
586
587
588
589
590
591
592
			else if (is_Unknown(upper))
				fputs("unknown ", f);
			else
				panic("Upper array bound is not constant");
		}
		break;
	}
593

594
	case tpo_method: {
Michael Beck's avatar
Michael Beck committed
595
596
597
		size_t nparams  = get_method_n_params(tp);
		size_t nresults = get_method_n_ress(tp);
		ir_fprintf(f, "%u %u %zu %zu ", get_method_calling_convention(tp),
598
599
			get_method_additional_properties(tp), nparams, nresults);
		for (i = 0; i < nparams; i++)
600
			write_long(env, get_type_nr(get_method_param_type(tp, i)));
601
		for (i = 0; i < nresults; i++)
602
			write_long(env, get_type_nr(get_method_res_type(tp, i)));
Michael Beck's avatar
Michael Beck committed
603
		ir_fprintf(f, "%zu ", get_method_first_variadic_param_index(tp));
604
605
		break;
	}
606

607
608
	case tpo_pointer:
		write_mode(env, get_type_mode(tp));
609
		write_long(env, get_type_nr(get_pointer_points_to_type(tp)));
610
		break;
611

612
613
614
615
616
617
618
619
	case tpo_enumeration:
		fprintf(stderr, "Enumeration type not handled yet by exporter\n");
		break;

	default:
		printf("export_type: Unknown type code \"%s\".\n",
		       get_type_tpop_name(tp));
		break;
620
621
622
623
624
625
	}
	fputc('\n', f);
}

static void export_entity(io_env_t *env, ir_entity *ent)
{
626
627
628
629
	FILE          *file       = env->file;
	ir_type       *owner      = get_entity_owner(ent);
	ir_visibility  visibility = get_entity_visibility(ent);
	ir_linkage     linkage    = get_entity_linkage(ent);
630
631
632
633
634
635
636

	/* we don't dump array_element_ent entities. They're a strange concept
	 * and lead to cycles in type_graph.
	 */
	if (is_Array_type(owner))
		return;

Matthias Braun's avatar
Matthias Braun committed
637
638
639
640
641
	fprintf(env->file, "\tentity ");
	write_long(env, get_entity_nr(ent));
	write_ident_null(env, get_entity_ident(ent));
	if (!entity_has_ld_ident(ent)) {
		write_ident_null(env, NULL);
642
	} else {
Matthias Braun's avatar
Matthias Braun committed
643
		write_ident_null(env, get_entity_ld_ident(ent));
644
645
	}

646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
	/* visibility + linkage */
	if (visibility != ir_visibility_default) {
		fprintf(file, "%s ", get_visibility_name(visibility));
	}
	if (linkage & IR_LINKAGE_CONSTANT)
		fputs("constant ", file);
	if (linkage & IR_LINKAGE_WEAK)
		fputs("weak ", file);
	if (linkage & IR_LINKAGE_GARBAGE_COLLECT)
		fputs("garbage_collect ", file);
	if (linkage & IR_LINKAGE_MERGE)
		fputs("merge ", file);
	if (linkage & IR_LINKAGE_HIDDEN_USER)
		fputs("hidden_user ", file);

	fprintf(file, "%ld %ld %d %u %d %s ",
662
663
664
			get_type_nr(get_entity_type(ent)),
			get_type_nr(owner),
			get_entity_offset(ent),
665
			(unsigned) get_entity_offset_bits_remainder(ent),
666
			is_entity_compiler_generated(ent),
667
668
			get_volatility_name(get_entity_volatility(ent)));

Matthias Braun's avatar
Matthias Braun committed
669
670
671
672
	if (ent->initializer != NULL) {
		fputs("initializer ", env->file);
		write_initializer(env, get_entity_initializer(ent));
	} else if (entity_has_compound_ent_values(ent)) {
Michael Beck's avatar
Michael Beck committed
673
		size_t i, n = get_compound_ent_n_values(ent);
Matthias Braun's avatar
Matthias Braun committed
674
		fputs("compoundgraph ", env->file);
Michael Beck's avatar
Michael Beck committed
675
		ir_fprintf(env->file, "%zu ", n);
Matthias Braun's avatar
Matthias Braun committed
676
677
678
679
		for (i = 0; i < n; i++) {
			ir_entity *member = get_compound_ent_value_member(ent, i);
			ir_node   *irn    = get_compound_ent_value(ent, i);
			fprintf(env->file, "%ld %ld ", get_entity_nr(member), get_irn_node_nr(irn));
680
		}
Matthias Braun's avatar
Matthias Braun committed
681
682
	} else {
		fputs("none", env->file);
683
684
685
	}

	fputc('\n', env->file);
686
687
}

688
689
690
static void export_type_or_ent_pre(type_or_ent tore, void *ctx)
{
	io_env_t *env = (io_env_t *) ctx;
Michael Beck's avatar
Michael Beck committed
691
	if (get_kind(tore.typ) == k_type)
692
693
694
695
		export_type_pre(env, tore.typ);
}

static void export_type_or_ent_post(type_or_ent tore, void *ctx)
696
697
698
{
	io_env_t *env = (io_env_t *) ctx;

699
700
701
702
	switch (get_kind(tore.ent)) {
	case k_entity:
		export_entity(env, tore.ent);
		break;
703

704
705
706
	case k_type:
		export_type_post(env, tore.typ);
		break;
707

708
709
710
	default:
		panic("export_type_or_ent_post: Unknown type or entity.");
		break;
711
712
713
	}
}

Matthias Braun's avatar
Matthias Braun committed
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
static void export_ASM(io_env_t *env, ir_node *node)
{
	ir_asm_constraint *input_constraints    = get_ASM_input_constraints(node);
	ir_asm_constraint *output_constraints   = get_ASM_output_constraints(node);
	ident            **clobbers             = get_ASM_clobbers(node);
	int                n_input_constraints  = get_ASM_n_input_constraints(node);
	int                n_output_constraints = get_ASM_n_output_constraints(node);
	int                n_clobbers           = get_ASM_n_clobbers(node);
	int i;

	write_ident(env, get_ASM_text(node));
	write_list_begin(env);
	for (i = 0; i < n_input_constraints; ++i) {
		const ir_asm_constraint *constraint = &input_constraints[i];
		write_unsigned(env, constraint->pos);
		write_ident(env, constraint->constraint);
		write_mode(env, constraint->mode);
	}
	write_list_end(env);

	write_list_begin(env);
	for (i = 0; i < n_output_constraints; ++i) {
		const ir_asm_constraint *constraint = &output_constraints[i];
		write_unsigned(env, constraint->pos);
		write_ident(env, constraint->constraint);
		write_mode(env, constraint->mode);
	}
	write_list_end(env);

	write_list_begin(env);
	for (i = 0; i < n_clobbers; ++i) {
		ident *clobber = clobbers[i];
		write_ident(env, clobber);
	}
	write_list_end(env);
}

751
752
753
/**
 * Walker: exports every node.
 */
754
755
756
757
758
759
static void export_node(ir_node *irn, void *ctx)
{
	io_env_t *env = (io_env_t *) ctx;
	int i, n;
	unsigned opcode = get_irn_opcode(irn);

Michael Beck's avatar
Michael Beck committed
760
	if (env->ignoreblocks && opcode == iro_Block)
761
		return;
762

763
764
	fprintf(env->file, "\t%s ", get_irn_opname(irn));
	write_long(env, get_irn_node_nr(irn));
765

766
	write_list_begin(env);
767
	n = get_irn_arity(irn);
768
	if (!is_Block(irn)) {
769
770
		ir_node *block = get_nodes_block(irn);
		write_long(env, get_irn_node_nr(block));
771
772
773
	}

	for (i = 0; i < n; i++) {
774
		ir_node *pred = get_irn_n(irn, i);
Michael Beck's avatar
Michael Beck committed
775
		if (pred == NULL) {
776
			/* Anchor node may have NULL predecessors */
777
			assert(is_Anchor(irn));
778
			fputs("-1 ", env->file);
779
		} else {
780
			write_long(env, get_irn_node_nr(pred));
781
		}
782
	}
783
	write_list_end(env);
784

785
	fputs("{ ", env->file);
786

787
	switch (opcode) {
788
789
790
791
792
793
794
795
796
797
798
799
800
801
	case iro_Start:
	case iro_End:
	case iro_Block:
	case iro_Anchor:
		break;
	case iro_SymConst:
		/* TODO: only symconst_addr_ent implemented yet */
		assert(get_SymConst_kind(irn) == symconst_addr_ent);
		fprintf(env->file, "%ld ", get_entity_nr(get_SymConst_entity(irn)));
		break;
	case iro_Proj:
		write_mode(env, get_irn_mode(irn));
		fprintf(env->file, "%ld ", get_Proj_proj(irn));
		break;
Matthias Braun's avatar
Matthias Braun committed
802
803
804
	case iro_ASM:
		export_ASM(env, irn);
		break;
805
#include "gen_irio_export.inl"
806
807
	default:
		panic("no export code for node %+F\n", irn);
808
	}
809
810
811
	fputs("}\n", env->file);
}

812
813
814
815
816
817
818
819
820
821
822
823
824
825
static const char *get_mode_sort_name(ir_mode_sort sort)
{
	switch (sort) {
	case irms_auxiliary:        return "auxiliary";
	case irms_control_flow:     return "control_flow";
	case irms_memory:           return "memory";
	case irms_internal_boolean: return "internal_boolean";
	case irms_reference:        return "reference";
	case irms_int_number:       return "int_number";
	case irms_float_number:     return "float_number";
	}
	panic("invalid mode sort found");
}

826
827
static void export_modes(io_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
828
	size_t i, n_modes = get_irp_n_modes();
829
830
831

	fputs("modes {\n", env->file);

Michael Beck's avatar
Michael Beck committed
832
	for (i = 0; i < n_modes; i++) {
833
		ir_mode *mode = get_irp_mode(i);
834
835
836
837
838
839
840
841
842
		switch (get_mode_sort(mode)) {
		case irms_auxiliary:
		case irms_control_flow:
		case irms_memory:
		case irms_internal_boolean:
			/* skip "internal" modes, which may not be user defined */
			continue;
		default:
			break;
843
844
		}

Matthias Braun's avatar
Matthias Braun committed
845
846
847
848
		fprintf(env->file, "\tmode ");
		write_string(env, get_mode_name(mode));
		fprintf(env->file, "%s %u %d %s %u %u ",
		        get_mode_sort_name(get_mode_sort(mode)),
849
850
851
852
		        get_mode_size_bits(mode), get_mode_sign(mode),
		        get_mode_arithmetic_name(get_mode_arithmetic(mode)),
		        get_mode_modulo_shift(mode),
		        get_mode_n_vector_elems(mode));
Michael Beck's avatar
Michael Beck committed
853
		if (mode_is_reference(mode)) {
854
855
856
857
858
859
			write_mode(env, get_reference_mode_signed_eq(mode));
			write_mode(env, get_reference_mode_unsigned_eq(mode));
		}
		fputc('\n', env->file);
	}

860
	fputs("}\n", env->file);
861
862
}

863
static void export_program(io_env_t *env)
864
{
865
866
867
868
869
	FILE         *f = env->file;
	ir_segment_t  s;

	fputs("\nprogram {\n", f);
	if (irp_prog_name_is_set()) {
Matthias Braun's avatar
Matthias Braun committed
870
871
872
		fprintf(f, "\tname ");
		write_string(env, get_irp_name());
		fputc('\n', f);
873
874
	}

875
	for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
876
		ir_type *segment_type = get_segment_type(s);
Matthias Braun's avatar
Matthias Braun committed
877
		fprintf(f, "\tsegment_type %s ", get_segment_name(s));
878
879
880
		if (segment_type == NULL) {
			fputs(" NULL\n", f);
		} else {
Matthias Braun's avatar
Matthias Braun committed
881
882
			write_long(env, get_type_nr(segment_type));
			fputc('\n', f);
883
884
885
886
		}
	}
	fputs("}\n", f);
}
887

888
889
890
891
void ir_export(const char *filename)
{
	FILE *file = fopen(filename, "wt");
	if (file == NULL) {
892
893
894
895
		perror(filename);
		return;
	}

896
897
898
	ir_export_file(file, filename);
	fclose(file);
}
899

900
901
902
903
/* Exports the whole irp to the given file in a textual form. */
void ir_export_file(FILE *file, const char *outputname)
{
	io_env_t env;
Michael Beck's avatar
Michael Beck committed
904
	size_t i, n_irgs = get_irp_n_irgs();
905
906
907
908
909

	(void) outputname;
	env.file = file;

	export_modes(&env);
910

911
	fputs("\ntypegraph {\n", env.file);
912
	type_walk_prog(export_type_or_ent_pre, export_type_or_ent_post, &env);
913
	fputs("}\n", env.file);
914

Michael Beck's avatar
Michael Beck committed
915
	for (i = 0; i < n_irgs; i++) {
916
917
		ir_graph *irg       = get_irp_irg(i);
		ir_type  *valuetype = get_irg_value_param_type(irg);
918

919
920
921
922
		fprintf(env.file, "\nirg %ld %ld %ld {\n",
		        get_entity_nr(get_irg_entity(irg)),
		        get_type_nr(get_irg_frame_type(irg)),
		        valuetype == NULL ? -1 : get_type_nr(valuetype));
923
924
925
926
927
928

		env.ignoreblocks = 0;
		irg_block_walk_graph(irg, NULL, export_node, &env);

		env.ignoreblocks = 1;
		irg_walk_anchors(irg, NULL, export_node, &env);
929
930

		fputs("}\n", env.file);
931
932
	}

933
	fprintf(env.file, "\nconstirg %ld {\n", get_irn_node_nr(get_const_code_irg()->current_block));
934

935
936
937
	walk_const_code(NULL, export_node, &env);
	fputs("}\n", env.file);

938
	export_program(&env);
939
940
}

941
/* Exports the given irg to the given file. */
942
void ir_export_irg(ir_graph *irg, FILE *file, const char *outputname)
943
944
945
{
	io_env_t env;

946
947
	(void) outputname;
	env.file = file;
948

949
950
	export_modes(&env);

951
952
	fputs("typegraph {\n", env.file);

953
	type_walk_irg(irg, export_type_or_ent_pre, export_type_or_ent_post, &env);
954

955
	fprintf(env.file, "}\n\nirg %ld {\n", get_entity_nr(get_irg_entity(irg)));
956
957
958
959
960
961
962

	env.ignoreblocks = 0;
	irg_block_walk_graph(irg, NULL, export_node, &env);

	env.ignoreblocks = 1;
	irg_walk_anchors(irg, NULL, export_node, &env);

963
	/* TODO: Only output needed constants */
964
	fprintf(env.file, "}\n\nconstirg %ld {\n", get_irn_node_nr(get_const_code_irg()->current_block));
965
966
	walk_const_code(NULL, export_node, &env);
	fputs("}\n", env.file);
Moritz Kroll's avatar
Moritz Kroll committed
967
968
}

969
static void read_c(io_env_t *env)
Moritz Kroll's avatar
Moritz Kroll committed
970
{
971
972
973
974
	int c = fgetc(env->file);
	env->c = c;
	if (c == '\n')
		env->line++;
Moritz Kroll's avatar
Moritz Kroll committed
975
976
}

977
978
/** Returns the first non-whitespace character or EOF. **/
static void skip_ws(io_env_t *env)
979
{
980
981
982
	while (true) {
		switch (env->c) {
		case ' ':
983
984
		case '\t':
		case '\n':
985
986
987
		case '\r':
			read_c(env);
			continue;
988
989

		default:
990
			return;
991
992
993
994
995
996
		}
	}
}

static void skip_to(io_env_t *env, char to_ch)
{
997
998
999
	while (env->c != to_ch && env->c != EOF) {
		read_c(env);
	}
1000
}
For faster browsing, not all history is shown. View entire blame