irio.c 38.2 KB
Newer Older
1
2
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
29
30
31
/*
 * Copyright (C) 1995-2009 University of Karlsruhe.  All right reserved.
 *
 * 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>

#include "irio.h"

32
#include "irnode_t.h"
33
34
35
36
37
38
39
40
41
42
43
#include "irprog.h"
#include "irgraph_t.h"
#include "ircons.h"
#include "irgmod.h"
#include "irflag_t.h"
#include "irgwalk.h"
#include "tv.h"
#include "array.h"
#include "error.h"
#include "adt/set.h"

44
#define SYMERROR ((unsigned) ~0)
45

Moritz Kroll's avatar
Moritz Kroll committed
46
typedef struct io_env_t
47
48
49
50
51
52
53
54
{
	FILE *file;
	set *idset;               /**< id_entry set, which maps from file ids to new Firm elements */
	int ignoreblocks;
	int line, col;
	ir_type **fixedtypes;
} io_env_t;

Moritz Kroll's avatar
Moritz Kroll committed
55
56
57
58
59
60
typedef struct lex_state_t
{
	long offs;
	int line, col;
} lex_state_t;

61
62
63
64
typedef enum typetag_t
{
	tt_align,
	tt_allocation,
65
	tt_builtin,
66
67
	tt_cond_kind,
	tt_cond_jmp_predicate,
68
69
	tt_initializer,
	tt_iro,
70
	tt_keyword,
71
	tt_mode_arithmetic,
72
73
	tt_peculiarity,
	tt_pin_state,
74
	tt_tpo,
75
76
77
	tt_type_state,
	tt_variability,
	tt_visibility,
78
	tt_volatility
79
80
} typetag_t;

81
82
83
84
85
86
typedef enum keyword_t
{
	kw_constirg,
	kw_entity,
	kw_frametype,
	kw_irg,
87
88
	kw_mode,
	kw_modes,
89
90
91
92
93
	kw_valuetype,
	kw_type,
	kw_typegraph
} keyword_t;

94
typedef struct symbol_t
95
{
96
97
98
99
	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;
100
101
102
103
104
105
106

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

107
108
/** The symbol table, a set of symbol_t elements. */
static set *symtbl;
109
110


111
112
113
114
/**
 * Calculate a hash value for a string.
 */
static unsigned string_hash(const char *str, int len)
115
116
117
118
{
	return str[0] * 27893 ^ str[len-1] * 81 ^ str[len >> 1];
}

119
120
121
122
/**
 * Compare two symbol table entries.
 */
static int symbol_cmp(const void *elt, const void *key, size_t size)
123
{
124
	int res;
125
126
	const symbol_t *entry = (const symbol_t *) elt;
	const symbol_t *keyentry = (const symbol_t *) key;
127
	(void) size;
128
	res = entry->typetag - keyentry->typetag;
Michael Beck's avatar
Michael Beck committed
129
	if (res) return res;
130
131
132
133
134
135
136
137
138
139
140
	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;
}

141
142
/** Initializes the symbol table. May be called more than once without problems. */
static void symtbl_init(void)
143
{
144
	symbol_t key;
145
146

	/* Only initialize once */
Michael Beck's avatar
Michael Beck committed
147
	if (symtbl != NULL)
148
		return;
149

150
	symtbl = new_set(symbol_cmp, 256);
151
152
153
154
155

#define INSERT(s, tt, cod)                                       \
	key.str = (s);                                               \
	key.typetag = (tt);                                          \
	key.code = (cod);                                            \
156
	set_insert(symtbl, &key, sizeof(key), string_hash(s, sizeof(s)-1) + tt * 17)
157
158

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

	INSERT("array", tt_tpo, tpo_array);
162
163
164
165
	INSERT("class", tt_tpo, tpo_class);
	INSERT("method", tt_tpo, tpo_method);
	INSERT("pointer", tt_tpo, tpo_pointer);
	INSERT("primitive", tt_tpo, tpo_primitive);
166
	INSERT("struct", tt_tpo, tpo_struct);
167
	INSERT("union", tt_tpo, tpo_union);
168
169
	INSERT("Unknown", tt_tpo, tpo_unknown);

170
171
172
173
	INSERTKEYWORD(constirg);
	INSERTKEYWORD(entity);
	INSERTKEYWORD(frametype);
	INSERTKEYWORD(irg);
174
175
	INSERTKEYWORD(mode);
	INSERTKEYWORD(modes);
176
177
178
179
	INSERTKEYWORD(valuetype);
	INSERTKEYWORD(type);
	INSERTKEYWORD(typegraph);

180
181
182
183
184
185
186
187
188
189
#include "gen_irio_lex.inl"

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

	INSERTENUM(tt_allocation, allocation_automatic);
	INSERTENUM(tt_allocation, allocation_parameter);
	INSERTENUM(tt_allocation, allocation_dynamic);
	INSERTENUM(tt_allocation, allocation_static);

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
	INSERTENUM(tt_builtin, ir_bk_trap);
	INSERTENUM(tt_builtin, ir_bk_debugbreak);
	INSERTENUM(tt_builtin, ir_bk_return_address);
	INSERTENUM(tt_builtin, ir_bk_frame_addess);
	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_kind, dense);
	INSERTENUM(tt_cond_kind, fragmentary);

	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);

217
218
219
220
221
222
223
224
	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);

225
226
227
228
	INSERTENUM(tt_peculiarity, peculiarity_description);
	INSERTENUM(tt_peculiarity, peculiarity_inherited);
	INSERTENUM(tt_peculiarity, peculiarity_existent);

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
	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_variability, variability_uninitialized);
	INSERTENUM(tt_variability, variability_initialized);
	INSERTENUM(tt_variability, variability_part_constant);
	INSERTENUM(tt_variability, variability_constant);

	INSERTENUM(tt_visibility, visibility_local);
	INSERTENUM(tt_visibility, visibility_external_visible);
	INSERTENUM(tt_visibility, visibility_external_allocated);

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

249
#undef INSERTKEYWORD
250
251
252
253
#undef INSERTENUM
#undef INSERT
}

254
255
/** 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)
256
{
257
	symbol_t key, *entry;
258
259

	key.str = str;
260
	key.typetag = typetag;
261

262
263
	entry = set_find(symtbl, &key, sizeof(key), string_hash(str, strlen(str)) + typetag * 17);
	return entry ? entry->code : SYMERROR;
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
}

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

	entry = set_find(env->idset, &key, sizeof(key), (unsigned) id);
	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);
}

static void write_mode(io_env_t *env, ir_mode *mode)
{
	fputs(get_mode_name(mode), env->file);
	fputc(' ', env->file);
}

289
290
291
292
293
294
295
296
297
static void write_tarval(io_env_t *env, tarval *tv)
{
	char buf[1024];
	write_mode(env, get_tarval_mode(tv));
	tarval_snprintf(buf, sizeof(buf), tv);
	fputs(buf, env->file);
	fputc(' ', env->file);
}

298
299
300
301
static void write_align(io_env_t *env, ir_node *irn)
{
	ir_align align;

Michael Beck's avatar
Michael Beck committed
302
303
304
305
306
307
	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");
308
309
310
311
312

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

313
314
315
316
317
318
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);
}

319
320
321
322
323
324
325
326
327
328
329
330
static void write_cond_kind(io_env_t *env, ir_node *irn)
{
	fputs(get_cond_kind_name(get_Cond_kind(irn)), env->file);
	fputc(' ', env->file);
}

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);
}

331
332
333
334
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);
335

336
337
338
	fputs(get_initializer_kind_name(ini_kind), f);
	fputc(' ', f);

Michael Beck's avatar
Michael Beck committed
339
	switch (ini_kind)
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
	{
		case IR_INITIALIZER_CONST:
			fprintf(f, "%ld ", get_irn_node_nr(get_initializer_const_value(ini)));
			break;

		case IR_INITIALIZER_TARVAL:
			write_tarval(env, get_initializer_tarval_value(ini));
			break;

		case IR_INITIALIZER_NULL:
			break;

		case IR_INITIALIZER_COMPOUND:
		{
			unsigned i, n = get_initializer_compound_n_entries(ini);
			fprintf(f, "%d ", n);
Michael Beck's avatar
Michael Beck committed
356
			for (i = 0; i < n; i++)
357
358
359
360
361
362
363
364
365
				write_initializer(env, get_initializer_compound_value(ini, i));
			break;
		}

		default:
			panic("Unknown initializer kind");
	}
}

366
367
368
369
370
371
372
373
374
375
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
376
377
378
379
380
381
	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");
382
383
384
385
386

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

387
static void export_type_common(io_env_t *env, ir_type *tp)
388
{
389
	fprintf(env->file, "\t%s %ld %s \"%s\" %u %u %s %s ",
390
			is_frame_type(tp) ? "frametype" : is_value_param_type(tp) ? "valuetype" : "type",
391
392
393
394
395
396
397
			get_type_nr(tp),
			get_type_tpop_name(tp),
			get_type_name(tp),
			get_type_size_bytes(tp),
			get_type_alignment_bytes(tp),
			get_type_state_name(get_type_state(tp)),
			get_visibility_name(get_type_visibility(tp)));
398
399
400
401
402
403
}

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

Michael Beck's avatar
Michael Beck committed
404
405
	/* skip types to be handled by post walker */
	switch (get_type_tpop_code(tp))
406
407
408
409
410
	{
		case tpo_array:
		case tpo_method:
		case tpo_pointer:
			return;
Matthias Braun's avatar
Matthias Braun committed
411
412
		default:
			break;
413
414
415
416
	}

	export_type_common(env, tp);

Michael Beck's avatar
Michael Beck committed
417
	switch (get_type_tpop_code(tp))
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
	{
		case tpo_class:
			/* TODO: inheritance stuff not supported yet */
			printf("Inheritance of classes not supported yet!\n");
			break;

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

		case tpo_struct:
			break;

		case tpo_union:
			break;

		case tpo_unknown:
			break;

		default:
			printf("export_type_pre: Unknown type code \"%s\".\n", get_type_tpop_name(tp));
			break;
	}
	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
447
	int i, n, nparams, nresults;
448

Michael Beck's avatar
Michael Beck committed
449
450
	/* skip types already handled by pre walker */
	switch (get_type_tpop_code(tp))
451
452
453
454
455
456
457
	{
		case tpo_class:
		case tpo_primitive:
		case tpo_struct:
		case tpo_union:
		case tpo_unknown:
			return;
Matthias Braun's avatar
Matthias Braun committed
458
459
		default:
			break;
460
461
462
	}

	export_type_common(env, tp);
463

Michael Beck's avatar
Michael Beck committed
464
	switch (get_type_tpop_code(tp))
465
466
	{
		case tpo_array:
Michael Beck's avatar
Michael Beck committed
467
			n = get_array_n_dimensions(tp);
468
			fprintf(f, "%i %ld ", n, get_type_nr(get_array_element_type(tp)));
Michael Beck's avatar
Michael Beck committed
469
			for (i = 0; i < n; i++) {
470
471
472
				ir_node *lower = get_array_lower_bound(tp, i);
				ir_node *upper = get_array_upper_bound(tp, i);

Michael Beck's avatar
Michael Beck committed
473
474
475
476
477
478
479
480
481
482
483
				if (is_Const(lower))
					fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(lower)));
				else
					panic("Lower array bound is not constant");

				if (is_Const(upper))
					fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(upper)));
				else if (is_Unknown(upper))
					fputs("unknown ", f);
				else
					panic("Upper array bound is not constant");
484
485
486
487
			}
			break;

		case tpo_method:
Michael Beck's avatar
Michael Beck committed
488
489
			nparams  = get_method_n_params(tp);
			nresults = get_method_n_ress(tp);
490
491
			fprintf(f, "0x%X 0x%X %i %i ", get_method_calling_convention(tp),
				get_method_additional_properties(tp), nparams, nresults);
Michael Beck's avatar
Michael Beck committed
492
			for (i = 0; i < nparams; i++)
493
				fprintf(f, "%ld ", get_type_nr(get_method_param_type(tp, i)));
Michael Beck's avatar
Michael Beck committed
494
			for (i = 0; i < nresults; i++)
495
				fprintf(f, "%ld ", get_type_nr(get_method_res_type(tp, i)));
Moritz Kroll's avatar
Moritz Kroll committed
496
			fprintf(f, "%d ", get_method_first_variadic_param_index(tp));
497
498
			break;

499
		case tpo_pointer:
500
			write_mode(env, get_type_mode(tp));
501
			fprintf(f, "%ld ", get_type_nr(get_pointer_points_to_type(tp)));
502
503
504
505
506
507
508
509
510
511
512
513
			break;

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

static void export_entity(io_env_t *env, ir_entity *ent)
{
	ir_type *owner = get_entity_owner(ent);
514
	fprintf(env->file, "\tentity %ld \"%s\" \"%s\" %ld %ld %d %u %s %s %s %s %s ",
515
516
			get_entity_nr(ent),
			get_entity_name(ent),
517
			ent->ld_name ? get_id_str(ent->ld_name) : "",
518
519
520
			get_type_nr(get_entity_type(ent)),
			get_type_nr(owner),
			get_entity_offset(ent),
521
			(unsigned) get_entity_offset_bits_remainder(ent),
522
523
524
525
526
527
			get_allocation_name(get_entity_allocation(ent)),
			get_visibility_name(get_entity_visibility(ent)),
			get_variability_name(get_entity_variability(ent)),
			get_peculiarity_name(get_entity_peculiarity(ent)),
			get_volatility_name(get_entity_volatility(ent)));

Michael Beck's avatar
Michael Beck committed
528
529
	/* TODO: inheritance stuff for class entities not supported yet */
	if (is_Class_type(owner) && owner != get_glob_type())
530
		printf("Inheritance of class entities not supported yet!\n");
531

Michael Beck's avatar
Michael Beck committed
532
533
	if (get_entity_variability(ent) != variability_uninitialized &&
	    get_entity_visibility(ent) != visibility_external_allocated)
534
	{
Michael Beck's avatar
Michael Beck committed
535
536
		if (is_compound_entity(ent)) {
			if (has_entity_initializer(ent)) {
537
538
				fputs("initializer ", env->file);
				write_initializer(env, get_entity_initializer(ent));
Michael Beck's avatar
Michael Beck committed
539
			} else {
540
				int i, n = get_compound_ent_n_values(ent);
541
				fputs("noninitializer ", env->file);
542
				fprintf(env->file, "%d ", n);
Michael Beck's avatar
Michael Beck committed
543
				for (i = 0; i < n; i++) {
544
545
546
547
					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));
				}
548
			}
Michael Beck's avatar
Michael Beck committed
549
		} else {
550
551
552
553
554
555
			ir_node *irn = get_atomic_ent_value(ent);
			fprintf(env->file, "%ld ", get_irn_node_nr(irn));
		}
	}

	fputc('\n', env->file);
556
557
}

558
559
560
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
561
	if (get_kind(tore.typ) == k_type)
562
563
564
565
		export_type_pre(env, tore.typ);
}

static void export_type_or_ent_post(type_or_ent tore, void *ctx)
566
567
568
{
	io_env_t *env = (io_env_t *) ctx;

Michael Beck's avatar
Michael Beck committed
569
	switch (get_kind(tore.ent))
570
571
572
573
574
575
	{
		case k_entity:
			export_entity(env, tore.ent);
			break;

		case k_type:
576
			export_type_post(env, tore.typ);
577
578
579
			break;

		default:
Michael Beck's avatar
Michael Beck committed
580
			panic("export_type_or_ent_post: Unknown type or entity.");
581
582
583
584
585
586
587
588
589
590
			break;
	}
}

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
591
	if (env->ignoreblocks && opcode == iro_Block)
592
		return;
593
594
595

	n = get_irn_arity(irn);

596
	fprintf(env->file, "\t%s %ld [ ", get_irn_opname(irn), get_irn_node_nr(irn));
597

Michael Beck's avatar
Michael Beck committed
598
	for (i = -1; i < n; i++) {
599
		ir_node *pred = get_irn_n(irn, i);
Michael Beck's avatar
Michael Beck committed
600
		if (pred == NULL) {
601
			/* Anchor node may have NULL predecessors */
602
			assert(is_Anchor(irn));
603
			fputs("-1 ", env->file);
604
		} else {
605
			fprintf(env->file, "%ld ", get_irn_node_nr(pred));
606
		}
607
608
609
610
	}

	fprintf(env->file, "] { ");

Michael Beck's avatar
Michael Beck committed
611
	switch (opcode)
612
613
614
	{
		#include "gen_irio_export.inl"
	}
615
616
617
	fputs("}\n", env->file);
}

618
619
620
621
622
623
static void export_modes(io_env_t *env)
{
	int i, n_modes = get_irp_n_modes();

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

Michael Beck's avatar
Michael Beck committed
624
	for (i = 0; i < n_modes; i++) {
625
		ir_mode *mode = get_irp_mode(i);
Michael Beck's avatar
Michael Beck committed
626
		switch (get_mode_sort(mode))
627
628
629
630
631
		{
			case irms_auxiliary:
			case irms_control_flow:
			case irms_memory:
			case irms_internal_boolean:
Michael Beck's avatar
Michael Beck committed
632
				/* skip "internal" modes, which may not be user defined */
633
				continue;
Matthias Braun's avatar
Matthias Braun committed
634
635
			default:
				break;
636
637
638
639
640
641
		}

		fprintf(env->file, "\tmode \"%s\" 0x%X %d %d %s %d %d ", get_mode_name(mode),
			get_mode_sort(mode), 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
642
		if (mode_is_reference(mode)) {
643
644
645
646
647
648
649
650
651
			write_mode(env, get_reference_mode_signed_eq(mode));
			write_mode(env, get_reference_mode_unsigned_eq(mode));
		}
		fputc('\n', env->file);
	}

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

652
653
654
655
/** Exports the whole irp to the given file in a textual form. */
void ir_export(const char *filename)
{
	io_env_t env;
656
	int i, n_irgs = get_irp_n_irgs();
657
658

	env.file = fopen(filename, "wt");
Michael Beck's avatar
Michael Beck committed
659
	if (!env.file) {
660
661
662
663
		perror(filename);
		return;
	}

664
665
	export_modes(&env);

666
667
	fputs("typegraph {\n", env.file);

668
	type_walk_plus_frames(export_type_or_ent_pre, export_type_or_ent_post, &env);
669
670
	/* TODO: Visit frame types and "types for value params"? */

Michael Beck's avatar
Michael Beck committed
671
	for (i = 0; i < n_irgs; i++) {
672
		ir_graph *irg = get_irp_irg(i);
673
		ir_type *valuetype = get_irg_value_param_type(irg);
674

675
676
677
		fprintf(env.file, "}\n\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));
678
679
680
681
682
683
684
685

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

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

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

688
689
690
691
	walk_const_code(NULL, export_node, &env);
	fputs("}\n", env.file);

	fclose(env.file);
692
693
694
695
696
697
698
699
}

/** Exports the given irg to the given file. */
void ir_export_irg(ir_graph *irg, const char *filename)
{
	io_env_t env;

	env.file = fopen(filename, "wt");
Michael Beck's avatar
Michael Beck committed
700
	if (!env.file) {
701
702
703
704
		perror(filename);
		return;
	}

705
706
	export_modes(&env);

707
708
	fputs("typegraph {\n", env.file);

709
	type_walk_irg(irg, export_type_or_ent_pre, export_type_or_ent_post, &env);
710

711
	fprintf(env.file, "}\n\nirg %ld {\n", get_entity_nr(get_irg_entity(irg)));
712
713
714
715
716
717
718

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

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

719
720
721
722
	/* TODO: Only output needed constants */
	fputs("}\n\nconstirg {\n", env.file);
	walk_const_code(NULL, export_node, &env);
	fputs("}\n", env.file);
723
724
725
726

	fclose(env.file);
}

Moritz Kroll's avatar
Moritz Kroll committed
727
728
729
730
731
732
733
734
735
736
737
738
739
740
static void save_lex_state(io_env_t *env, lex_state_t *state)
{
	state->offs = ftell(env->file);
	state->line = env->line;
	state->col  = env->col;
}

static void restore_lex_state(io_env_t *env, lex_state_t *state)
{
	fseek(env->file, state->offs, SEEK_SET);
	env->line = state->line;
	env->col  = state->col;
}

741
742
743
static int read_c(io_env_t *env)
{
	int ch = fgetc(env->file);
Michael Beck's avatar
Michael Beck committed
744
	switch (ch)
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
	{
		case '\t':
			env->col += 4;
			break;

		case '\n':
			env->col = 0;
			env->line++;
			break;

		default:
			env->col++;
			break;
	}
	return ch;
}

/** Returns the first non-whitespace character or EOF. **/
static int skip_ws(io_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
765
	while (1)
766
767
	{
		int ch = read_c(env);
Michael Beck's avatar
Michael Beck committed
768
		switch (ch)
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
		{
			case ' ':
			case '\t':
			case '\n':
			case '\r':
				break;

			default:
				return ch;
		}
	}
}

static void skip_to(io_env_t *env, char to_ch)
{
	int ch;
	do
		ch = read_c(env);
Michael Beck's avatar
Michael Beck committed
787
	while (ch != to_ch && ch != EOF);
788
789
790
791
792
}

static int expect_char(io_env_t *env, char ch)
{
	int curch = skip_ws(env);
Michael Beck's avatar
Michael Beck committed
793
	if (curch != ch) {
794
795
796
797
798
799
		printf("Unexpected char '%c', expected '%c' in line %i:%i\n", curch, ch, env->line, env->col);
		return 0;
	}
	return 1;
}

Michael Beck's avatar
Michael Beck committed
800
801
#define EXPECT(c) if (expect_char(env, (c))) {} else return 0
#define EXPECT_OR_EXIT(c) if (expect_char(env, (c))) {} else exit(1)
802
803
804
805

inline static const char *read_str_to(io_env_t *env, char *buf, size_t bufsize)
{
	size_t i;
Michael Beck's avatar
Michael Beck committed
806
	for (i = 0; i < bufsize - 1; i++) {
807
		int ch = read_c(env);
Michael Beck's avatar
Michael Beck committed
808
809
		if (ch == EOF) break;
		switch (ch)
810
811
812
813
814
		{
			case ' ':
			case '\t':
			case '\n':
			case '\r':
Michael Beck's avatar
Michael Beck committed
815
				if (i != 0)
816
					goto endofword;
Michael Beck's avatar
Michael Beck committed
817
				i--;	/* skip whitespace */
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
				break;

			default:
				buf[i] = ch;
				break;
		}
	}
endofword:
	buf[i] = 0;
	return buf;
}

static const char *read_str(io_env_t *env)
{
	static char buf[1024];
	return read_str_to(env, buf, sizeof(buf));
}

static const char *read_qstr_to(io_env_t *env, char *buf, size_t bufsize)
{
	size_t i;
	EXPECT_OR_EXIT('\"');
Michael Beck's avatar
Michael Beck committed
840
	for (i = 0; i < bufsize - 1; i++) {
841
		int ch = read_c(env);
Michael Beck's avatar
Michael Beck committed
842
		if (ch == EOF) {
843
844
845
			printf("Unexpected end of quoted string!\n");
			exit(1);
		}
Michael Beck's avatar
Michael Beck committed
846
		if (ch == '\"') break;
847
848
849

		buf[i] = ch;
	}
Michael Beck's avatar
Michael Beck committed
850
	if (i == bufsize - 1) {
851
852
853
854
855
856
857
		printf("Quoted string too long!\n");
		exit(1);
	}
	buf[i] = 0;
	return buf;
}

858
859
860
861
862
863
static const char *read_qstr(io_env_t *env)
{
	static char buf[1024];
	return read_qstr_to(env, buf, sizeof(buf));
}

864
865
866
867
868
869
870
871
872
873
874
875
876
877
static long read_long2(io_env_t *env, char **endptr)
{
	static char buf[1024];
	return strtol(read_str_to(env, buf, sizeof(buf)), endptr, 0);
}

static long read_long(io_env_t *env)
{
	return read_long2(env, NULL);
}

static ir_node *get_node_or_null(io_env_t *env, long nodenr)
{
	ir_node *node = (ir_node *) get_id(env, nodenr);
Michael Beck's avatar
Michael Beck committed
878
	if (node && node->kind != k_ir_node)
879
880
881
882
883
884
885
		panic("Irn ID %ld collides with something else in line %i:%i\n", nodenr, env->line, env->col);
	return node;
}

static ir_node *get_node(io_env_t *env, long nodenr)
{
	ir_node *node = get_node_or_null(env, nodenr);
Michael Beck's avatar
Michael Beck committed
886
	if (!node)
887
888
889
890
891
892
893
894
		panic("Unknown node: %ld in line %i:%i\n", nodenr, env->line, env->col);

	return node;
}

static ir_node *get_node_or_dummy(io_env_t *env, long nodenr)
{
	ir_node *node = get_node_or_null(env, nodenr);
Michael Beck's avatar
Michael Beck committed
895
	if (node == NULL) {
896
897
898
899
900
901
902
903
904
		node = new_Dummy(mode_X);
		set_id(env, nodenr, node);
	}
	return node;
}

static ir_type *get_type(io_env_t *env, long typenr)
{
	ir_type *type = (ir_type *) get_id(env, typenr);
Michael Beck's avatar
Michael Beck committed
905
	if (type == NULL)
906
		panic("Unknown type: %ld in line %i:%i\n", typenr, env->line, env->col);
Michael Beck's avatar
Michael Beck committed
907
	else if (type->kind != k_type)
908
909
910
911
912
913
914
915
916
917
918
919
		panic("Type ID %ld collides with something else in line %i:%i\n", typenr, env->line, env->col);
	return type;
}

static ir_type *read_type(io_env_t *env)
{
	return get_type(env, read_long(env));
}

static ir_entity *get_entity(io_env_t *env, long entnr)
{
	ir_entity *entity = (ir_entity *) get_id(env, entnr);
Michael Beck's avatar
Michael Beck committed
920
	if (entity == NULL) {
921
922
		printf("Unknown entity: %ld in line %i:%i\n", entnr, env->line, env->col);
		exit(1);
Michael Beck's avatar
Michael Beck committed
923
	} else if (entity->kind != k_entity)
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
		panic("Entity ID %ld collides with something else in line %i:%i\n", entnr, env->line, env->col);
	return entity;
}

static ir_entity *read_entity(io_env_t *env)
{
	return get_entity(env, read_long(env));
}

static ir_mode *read_mode(io_env_t *env)
{
	static char buf[128];
	int i, n;

	read_str_to(env, buf, sizeof(buf));

	n = get_irp_n_modes();
Michael Beck's avatar
Michael Beck committed
941
	for (i = 0; i < n; i++) {
942
		ir_mode *mode = get_irp_mode(i);
Michael Beck's avatar
Michael Beck committed
943
		if (!strcmp(buf, get_mode_name(mode)))
944
945
946
947
948
949
950
951
952
			return mode;
	}

	printf("Unknown mode \"%s\" in line %i:%i\n", buf, env->line, env->col);
	return mode_ANY;
}

static const char *get_typetag_name(typetag_t typetag)
{
Michael Beck's avatar
Michael Beck committed
953
	switch (typetag)
954
955
956
	{
		case tt_align:       return "align";
		case tt_allocation:  return "allocation";
957
958
959
		case tt_builtin:     return "builtin kind";
		case tt_initializer: return "initializer kind";
		case tt_iro:         return "opcode";
960
961
		case tt_peculiarity: return "peculiarity";
		case tt_pin_state:   return "pin state";
962
		case tt_tpo:         return "type";
963
964
965
966
967
968
969
970
		case tt_type_state:  return "type state";
		case tt_variability: return "variability";
		case tt_visibility:  return "visibility";
		case tt_volatility:  return "volatility";
		default: return "<UNKNOWN>";
	}
}

971
972
973
/**
 * Read and decode an enum constant.
 */
974
975
976
static unsigned read_enum(io_env_t *env, typetag_t typetag)
{
	static char buf[128];
977
	unsigned code = symbol(read_str_to(env, buf, sizeof(buf)), typetag);
Michael Beck's avatar
Michael Beck committed
978
	if (code != SYMERROR)
979
		return code;
980
981
982
983
984

	printf("Invalid %s: \"%s\" in %i:%i\n", get_typetag_name(typetag), buf, env->line, env->col);
	return 0;
}

985
986
987
988
989
990
#define read_align(env)              ((ir_align)              read_enum(env, tt_align))
#define read_allocation(env)         ((ir_allocation)         read_enum(env, tt_allocation))
#define read_builtin_kind(env)       ((ir_builtin_kind)       read_enum(env, tt_builtin))
#define read_cond_kind(env)          ((cond_kind)             read_enum(env, tt_cond_kind))
#define read_cond_jmp_predicate(env) ((cond_jmp_predicate)    read_enum(env, tt_cond_jmp_predicate))
#define read_initializer_kind(env)   ((ir_initializer_kind_t) read_enum(env, tt_initializer))
991
#define read_mode_arithmetic(env)    ((ir_mode_arithmetic)    read_enum(env, tt_mode_arithmetic))
992
993
994
995
996
997
#define read_peculiarity(env)        ((ir_peculiarity)        read_enum(env, tt_peculiarity))
#define read_pin_state(env)          ((op_pin_state)          read_enum(env, tt_pin_state))
#define read_type_state(env)         ((ir_type_state)         read_enum(env, tt_type_state))
#define read_variability(env)        ((ir_variability)        read_enum(env, tt_variability))
#define read_visibility(env)         ((ir_visibility)         read_enum(env, tt_visibility))
#define read_volatility(env)         ((ir_volatility)         read_enum(env, tt_volatility))
998

999
1000
1001
1002
1003
static ir_cons_flags get_cons_flags(io_env_t *env)
{
	ir_cons_flags flags = cons_none;

	op_pin_state pinstate = read_pin_state(env);
Michael Beck's avatar
Michael Beck committed
1004
	switch (pinstate)
1005
1006
1007
1008
1009
1010
1011
	{
		case op_pin_state_floats: flags |= cons_floats; break;
		case op_pin_state_pinned: break;
		default:
			panic("Error in %i:%i: Invalid pinstate: %s", env->line, env->col, get_op_pin_state_name(pinstate));
	}

Michael Beck's avatar
Michael Beck committed
1012
1013
1014
1015
	if (read_volatility(env) == volatility_is_volatile)
		flags |= cons_volatile;
	if (read_align(env) == align_non_aligned)
		flags |= cons_unaligned;
1016
1017
1018
1019

	return flags;
}

1020
1021
1022
1023
1024
1025
1026
1027
static tarval *read_tv(io_env_t *env)
{
	static char buf[128];
	ir_mode *tvmode = read_mode(env);
	read_str_to(env, buf, sizeof(buf));
	return new_tarval_from_str(buf, strlen(buf), tvmode);
}

1028
1029
1030
1031
static ir_initializer_t *read_initializer(io_env_t *env)
{
	ir_initializer_kind_t ini_kind = read_initializer_kind(env);

Michael Beck's avatar
Michael Beck committed
1032
	switch (ini_kind)
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
	{
		case IR_INITIALIZER_CONST:
		{
			ir_node *irn = get_node_or_dummy(env, read_long(env));
			return create_initializer_const(irn);
		}

		case IR_INITIALIZER_TARVAL:
			return create_initializer_tarval(read_tv(env));

		case IR_INITIALIZER_NULL:
			return get_initializer_null();

		case IR_INITIALIZER_COMPOUND:
		{
			unsigned i, n = (unsigned) read_long(env);
			ir_initializer_t *ini = create_initializer_compound(n);
Michael Beck's avatar
Michael Beck committed
1050
			for (i = 0; i < n; i++) {
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
				ir_initializer_t *curini = read_initializer(env);
				set_initializer_compound_value(ini, i, curini);
			}
			return ini;
		}

		default:
			panic("Unknown initializer kind");
	}
}


1063
/** Reads a type description and remembers it by its id. */
1064
static void import_type(io_env_t *env, keyword_t kwkind)
1065
1066
1067
1068
1069
{
	int            i;
	ir_type       *type;
	long           typenr = read_long(env);
	const char    *tpop   = read_str(env);
1070
	const char    *name   = read_qstr(env);
1071
1072
1073
1074
1075
1076
1077
	unsigned       size   = (unsigned) read_long(env);
	unsigned       align  = (unsigned) read_long(env);
	ir_type_state  state  = read_type_state(env);
	ir_visibility  vis    = read_visibility(env);

	ident         *id     = new_id_from_str(name);

1078
1079
	const char    *kindstr;

Michael Beck's avatar
Michael Beck committed
1080
1081
	if (kwkind == kw_frametype) {
		if (symbol(tpop, tt_tpo) != tpo_class) {
1082
1083
1084
			printf("Frame type must be a class type in line %i:%i\n", env->line, env->col);
			skip_to(env, '\n');
			return;
1085
1086
		}

1087
1088
		type = new_type_frame(id);
		set_type_size_bytes(type, size);
1089

1090
		kindstr = "frametype";
Michael Beck's avatar
Michael Beck committed
1091
1092
	} else if (kwkind == kw_valuetype) {
		if (symbol(tpop, tt_tpo) != tpo_struct) {
1093
1094
1095
1096
			printf("Value type must be a struct type in line %i:%i\n", env->line, env->col);
			skip_to(env, '\n');
			return;
		}
1097

1098
1099
		type = new_type_value(id);
		set_type_size_bytes(type, size);
1100

1101
		kindstr = "valuetype";
Michael Beck's avatar
Michael Beck committed
1102
1103
	} else {
		switch (symbol(tpop, tt_tpo))
1104
1105
		{
			case tpo_array:
1106
			{
1107
1108
1109
				int ndims = (int) read_long(env);
				long elemtypenr = read_long(env);
				ir_type *elemtype = get_type(env, elemtypenr);
1110

1111
				type = new_type_array(id, ndims, elemtype);
Michael Beck's avatar
Michael Beck committed
1112
				for (i = 0; i < ndims; i++) {
1113
					const char *str = read_str(env);
Michael Beck's avatar
Michael Beck committed
1114
					if (strcmp(str, "unknown") != 0) {
1115
1116
1117
1118
						long lowerbound = strtol(str, NULL, 0);
						set_array_lower_bound_int(type, i, lowerbound);
					}
					str = read_str(env);
Michael Beck's avatar
Michael Beck committed
1119
					if (strcmp(str, "unknown") != 0) {
1120
1121
1122
1123
1124
1125
						long upperbound = strtol(str, NULL, 0);
						set_array_upper_bound_int(type, i, upperbound);
					}
				}
				set_type_size_bytes(type, size);
				break;
1126
			}
1127
1128
1129
1130
1131
1132
1133

			case tpo_class:
				type = new_type_class(id);
				set_type_size_bytes(type, size);
				break;

			case tpo_method:
1134
			{
1135
1136
1137
1138
				unsigned callingconv = (unsigned) read_long(env);
				unsigned addprops    = (unsigned) read_long(env);
				int nparams          = (int)      read_long(env);
				int nresults         = (int)      read_long(env);
Moritz Kroll's avatar
Moritz Kroll committed
1139
				int variaindex;
1140

1141
				type = new_type_method(id, nparams, nresults);
1142

Michael Beck's avatar
Michael Beck committed
1143
				for (i = 0; i < nparams; i++) {
1144
1145
					long     typenr = read_long(env);
					ir_type *paramtype = get_type(env, typenr);
1146

1147
1148
					set_method_param_type(type, i, paramtype);
				}
Michael Beck's avatar
Michael Beck committed
1149
				for (i = 0; i < nresults; i++) {
1150
1151
					long typenr = read_long(env);
					ir_type *restype = get_type(env, typenr);
1152

1153
1154
					set_method_res_type(type, i, restype);
				}
1155

Moritz Kroll's avatar
Moritz Kroll committed
1156
				variaindex = (int) read_long(env);
Michael Beck's avatar
Michael Beck committed
1157
				if (variaindex != -1) {
Moritz Kroll's avatar
Moritz Kroll committed
1158
					set_method_variadicity(type, variadicity_variadic);
Michael Beck's avatar
Michael Beck committed
1159
					if (variaindex != nparams)
Moritz Kroll's avatar
Moritz Kroll committed
1160
1161
1162
						set_method_first_variadic_param_index(type, variaindex);
				}

1163
1164
1165
1166
				set_method_calling_convention(type, callingconv);
				set_method_additional_properties(type, addprops);
				break;
			}
1167

1168
1169
1170
1171
1172
1173
1174
			case tpo_pointer:
			{
				ir_mode *mode = read_mode(env);
				ir_type *pointsto = get_type(env, read_long(env));
				type = new_type_pointer(id, pointsto, mode);
				break;
			}
1175

1176
1177
1178
1179
1180
1181
			case tpo_primitive:
			{
				ir_mode *mode = read_mode(env);
				type = new_type_primitive(id, mode);
				break;
			}
1182

1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
			case tpo_struct:
				type = new_type_struct(id);
				set_type_size_bytes(type, size);
				break;

			case tpo_union:
				type = new_type_union(id);
				set_type_size_bytes(type, size);
				break;

			case tpo_unknown:
Michael Beck's avatar
Michael Beck committed
1194
				return;   /* ignore unknown type */
1195
1196

			default:
Michael Beck's avatar
Michael Beck committed
1197
				if (typenr != 0)  /* ignore global type */
1198
1199
1200
1201
1202
					printf("Unknown type kind: \"%s\" in line %i:%i\n", tpop, env->line, env->col);
				skip_to(env, '\n');
				return;
		}
		kindstr = "type";
1203
1204
1205
1206
1207
	}

	set_type_alignment_bytes(type, align);
	set_type_visibility(type, vis);

Michael Beck's avatar
Michael Beck committed
1208
	if (state == layout_fixed)
1209
1210
1211
		ARR_APP1(ir_type *, env->fixedtypes, type);

	set_id(env, typenr, type);
1212
	printf("Insert %s %s %ld\n", kindstr, name, typenr);
1213
1214
1215
1216
1217
}

/** Reads an entity description and remembers it by its id. */
static void import_entity(io_env_t *env)
{
1218
	char          buf[1024], buf2[1024];
1219
1220
	long          entnr       = read_long(env);
	const char   *name        = read_qstr_to(env, buf, sizeof(buf));
1221
	const char   *ld_name     = read_qstr_to(env, buf2, sizeof(buf2));
1222
1223
1224
1225
1226
1227
1228
	long          typenr      = read_long(env);
	long          ownertypenr = read_long(env);

	ir_type   *type      = get_type(env, typenr);
	ir_type   *ownertype = !ownertypenr ? get_glob_type() : get_type(env, ownertypenr);
	ir_entity *entity    = new_entity(ownertype, new_id_from_str(name), type);

Michael Beck's avatar
Michael Beck committed
1229
1230
	if (*ld_name)
		set_entity_ld_ident(entity, new_id_from_str(ld_name));
1231
1232
1233
1234
1235
1236
1237
1238
	set_entity_offset     (entity, (int) read_long(env));
	set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
	set_entity_allocation (entity, read_allocation(env));
	set_entity_visibility (entity, read_visibility(env));
	set_entity_variability(entity, read_variability(env));
	set_entity_peculiarity(entity, read_peculiarity(env));
	set_entity_volatility (entity, read_volatility(env));

Michael Beck's avatar
Michael Beck committed
1239
1240
	if (get_entity_variability(entity) != variability_uninitialized &&
	    get_entity_visibility(entity) != visibility_external_allocated)
1241
	{
Michael Beck's avatar
Michael Beck committed
1242
1243
		if (is_compound_entity(entity)) {
			if (!strcmp(read_str_to(env, buf2, sizeof(buf2)), "initializer")) {
1244
				set_entity_initializer(entity, read_initializer(env));
Michael Beck's avatar
Michael Beck committed
1245
			} else {
1246
				int i, n = (int) read_long(env);
Michael Beck's avatar
Michael Beck committed
1247
				for (i = 0; i < n; i++) {
1248
1249
1250
1251
					ir_entity *member = get_entity(env, read_long(env));
					ir_node</