irio.c 55.9 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
 */

/**
 * @file
 * @brief   Write textual representation of firm to file.
Matthias Braun's avatar
Matthias Braun committed
9
 * @author  Moritz Kroll, Matthias Braun
10
 */
11
12
#include "irio.h"

13
#include <string.h>
14
15
16
#include <ctype.h>
#include <stdbool.h>
#include <stdarg.h>
17

18
#include "array.h"
Matthias Braun's avatar
Matthias Braun committed
19
#include "ircons_t.h"
20
#include "irflag_t.h"
21
22
#include "irgmod.h"
#include "irgraph_t.h"
23
#include "irgwalk.h"
24
25
26
#include "irio_t.h"
#include "irprintf.h"
#include "irprog_t.h"
Matthias Braun's avatar
Matthias Braun committed
27
#include "obst.h"
28
#include "panic.h"
Matthias Braun's avatar
Matthias Braun committed
29
#include "pmap.h"
30
#include "tv_t.h"
Christoph Mallon's avatar
Christoph Mallon committed
31
#include "util.h"
32

33
#define SYMERROR ((unsigned) ~0)
34

Matthias Braun's avatar
Matthias Braun committed
35
typedef enum typetag_t {
36
	tt_align,
Matthias Braun's avatar
Matthias Braun committed
37
	tt_builtin_kind,
38
	tt_cond_jmp_predicate,
39
	tt_initializer,
40
	tt_keyword,
Matthias Braun's avatar
Matthias Braun committed
41
	tt_linkage,
42
	tt_loop,
43
	tt_mode_arithmetic,
44
	tt_pin_state,
Matthias Braun's avatar
Matthias Braun committed
45
46
	tt_segment,
	tt_throws,
47
	tt_tpo,
48
	tt_type_state,
Matthias Braun's avatar
Matthias Braun committed
49
	tt_visibility,
50
	tt_volatility,
51
52
} typetag_t;

Matthias Braun's avatar
Matthias Braun committed
53
54
55
typedef enum keyword_t {
	kw_asm,
	kw_compound_member,
56
57
	kw_constirg,
	kw_entity,
58
	kw_float_mode,
Matthias Braun's avatar
Matthias Braun committed
59
60
	kw_int_mode,
	kw_irg,
61
	kw_alias,
Matthias Braun's avatar
Matthias Braun committed
62
	kw_gotentry,
Matthias Braun's avatar
Matthias Braun committed
63
64
	kw_label,
	kw_method,
65
	kw_modes,
Matthias Braun's avatar
Matthias Braun committed
66
67
68
69
	kw_parameter,
	kw_program,
	kw_reference_mode,
	kw_segment_type,
70
	kw_type,
71
	kw_typegraph,
72
	kw_unknown,
73
74
} keyword_t;

Matthias Braun's avatar
Matthias Braun committed
75
typedef struct symbol_t {
76
77
78
79
	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;
80

Matthias Braun's avatar
Matthias Braun committed
81
typedef struct id_entry {
82
83
84
85
	long id;
	void *elem;
} id_entry;

86
87
/** The symbol table, a set of symbol_t elements. */
static set *symtbl;
88

89
90
91
92
/**
 * Compare two symbol table entries.
 */
static int symbol_cmp(const void *elt, const void *key, size_t size)
93
{
Matthias Braun's avatar
cleanup    
Matthias Braun committed
94
	(void)size;
95
96
	const symbol_t *entry = (const symbol_t *) elt;
	const symbol_t *keyentry = (const symbol_t *) key;
Matthias Braun's avatar
Matthias Braun committed
97
98
99
	int res = entry->typetag - keyentry->typetag;
	if (res != 0)
		return res;
100
101
102
103
104
	return strcmp(entry->str, keyentry->str);
}

static int id_cmp(const void *elt, const void *key, size_t size)
{
Matthias Braun's avatar
cleanup    
Matthias Braun committed
105
	(void)size;
106
107
108
109
110
	const id_entry *entry = (const id_entry *) elt;
	const id_entry *keyentry = (const id_entry *) key;
	return entry->id - keyentry->id;
}

111
static void FIRM_PRINTF(2, 3)
Matthias Braun's avatar
Matthias Braun committed
112
parse_error(read_env_t *env, const char *fmt, ...)
113
114
115
{
	/* workaround read_c "feature" that a '\n' triggers the line++
	 * instead of the character after the '\n' */
Matthias Braun's avatar
Matthias Braun committed
116
	unsigned line = env->line;
117
118
119
120
	if (env->c == '\n') {
		line--;
	}

Matthias Braun's avatar
Matthias Braun committed
121
122
123
	fprintf(stderr, "%s:%u: error ", env->inputname, line);
	env->read_errors = true;

Matthias Braun's avatar
Matthias Braun committed
124
	va_list ap;
125
126
127
128
129
	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);
}

130
131
/** Initializes the symbol table. May be called more than once without problems. */
static void symtbl_init(void)
132
133
{
	/* Only initialize once */
Michael Beck's avatar
Michael Beck committed
134
	if (symtbl != NULL)
135
		return;
136

137
	symtbl = new_set(symbol_cmp, 256);
138

Matthias Braun's avatar
Matthias Braun committed
139
	symbol_t key;
140
#define INSERT(tt, s, cod)                                       \
141
142
143
	key.str = (s);                                               \
	key.typetag = (tt);                                          \
	key.code = (cod);                                            \
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
144
	(void)set_insert(symbol_t, symtbl, &key, sizeof(key), hash_str(s) + tt * 17)
145
146
147
148
149
150
151
152
153

#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);
154
	INSERT(tt_tpo, "segment", tpo_segment);
155
156
157
158
159
160
161
162
	INSERT(tt_tpo, "struct", tpo_struct);
	INSERT(tt_tpo, "union", tpo_union);
	INSERT(tt_tpo, "Unknown", tpo_unknown);

	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);
Matthias Braun's avatar
Matthias Braun committed
163
	INSERT(tt_segment, "jcr", IR_SEGMENT_JCR);
164

Matthias Braun's avatar
Matthias Braun committed
165
166
167
168
169
170
	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);

171
172
173
	INSERT(tt_loop, "loop",   true);
	INSERT(tt_loop, "noloop", false);

174
175
176
177
178
	INSERT(tt_visibility, "external",           ir_visibility_external);
	INSERT(tt_visibility, "external_private",   ir_visibility_external_private);
	INSERT(tt_visibility, "external_protected", ir_visibility_external_protected);
	INSERT(tt_visibility, "local",              ir_visibility_local);
	INSERT(tt_visibility, "private",            ir_visibility_private);
179

Matthias Braun's avatar
Matthias Braun committed
180
181
182
	INSERT(tt_throws, "throw",   true);
	INSERT(tt_throws, "nothrow", false);

183
	INSERTKEYWORD(alias);
Matthias Braun's avatar
Matthias Braun committed
184
185
	INSERTKEYWORD(asm);
	INSERTKEYWORD(compound_member);
186
187
	INSERTKEYWORD(constirg);
	INSERTKEYWORD(entity);
188
	INSERTKEYWORD(float_mode);
Matthias Braun's avatar
Matthias Braun committed
189
	INSERTKEYWORD(gotentry);
Matthias Braun's avatar
Matthias Braun committed
190
191
192
193
	INSERTKEYWORD(int_mode);
	INSERTKEYWORD(irg);
	INSERTKEYWORD(label);
	INSERTKEYWORD(method);
194
	INSERTKEYWORD(modes);
Matthias Braun's avatar
Matthias Braun committed
195
	INSERTKEYWORD(parameter);
196
	INSERTKEYWORD(program);
Matthias Braun's avatar
Matthias Braun committed
197
	INSERTKEYWORD(reference_mode);
198
	INSERTKEYWORD(segment_type);
Matthias Braun's avatar
Matthias Braun committed
199
200
	INSERTKEYWORD(type);
	INSERTKEYWORD(typegraph);
201
	INSERTKEYWORD(unknown);
202
203
204
205

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

Matthias Braun's avatar
Matthias Braun committed
206
207
208
209
210
211
212
213
214
215
216
217
218
	INSERTENUM(tt_builtin_kind, ir_bk_trap);
	INSERTENUM(tt_builtin_kind, ir_bk_debugbreak);
	INSERTENUM(tt_builtin_kind, ir_bk_return_address);
	INSERTENUM(tt_builtin_kind, ir_bk_frame_address);
	INSERTENUM(tt_builtin_kind, ir_bk_prefetch);
	INSERTENUM(tt_builtin_kind, ir_bk_ffs);
	INSERTENUM(tt_builtin_kind, ir_bk_clz);
	INSERTENUM(tt_builtin_kind, ir_bk_ctz);
	INSERTENUM(tt_builtin_kind, ir_bk_popcount);
	INSERTENUM(tt_builtin_kind, ir_bk_parity);
	INSERTENUM(tt_builtin_kind, ir_bk_bswap);
	INSERTENUM(tt_builtin_kind, ir_bk_inport);
	INSERTENUM(tt_builtin_kind, ir_bk_outport);
219
	INSERTENUM(tt_builtin_kind, ir_bk_saturating_increment);
220
	INSERTENUM(tt_builtin_kind, ir_bk_compare_swap);
221
222
223
224
225
226
227
228
229
230

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

Matthias Braun's avatar
Matthias Braun committed
231
232
233
234
235
	INSERT(tt_mode_arithmetic, "none",               irma_none);
	INSERT(tt_mode_arithmetic, "twos_complement",    irma_twos_complement);
	INSERT(tt_mode_arithmetic, "ieee754",            irma_ieee754);
	INSERT(tt_mode_arithmetic, "x86_extended_float", irma_x86_extended_float);

236
237
238
239
240
241
242
243
244
245
	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_type_state, layout_undefined);
	INSERTENUM(tt_type_state, layout_fixed);

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

246
#undef INSERTKEYWORD
247
248
249
250
#undef INSERTENUM
#undef INSERT
}

251
252
253
254
255
256
257
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";
Matthias Braun's avatar
Matthias Braun committed
258
	case IR_SEGMENT_JCR:          return "jcr";
259
	}
260
	panic("invalid segment");
261
262
}

263
264
265
static const char *get_visibility_name(ir_visibility visibility)
{
	switch (visibility) {
266
267
268
269
270
	case ir_visibility_external:           return "external";
	case ir_visibility_external_private:   return "external_private";
	case ir_visibility_external_protected: return "external_protected";
	case ir_visibility_local:              return "local";
	case ir_visibility_private:            return "private";
271
	}
272
	panic("invalid visibility");
Matthias Braun's avatar
Matthias Braun committed
273
274
275
276
277
278
279
280
281
282
283
284
285
}

static const char *get_mode_arithmetic_name(ir_mode_arithmetic arithmetic)
{
	switch (arithmetic) {
	case irma_none:               return "none";
	case irma_twos_complement:    return "twos_complement";
	case irma_ieee754:            return "ieee754";
	case irma_x86_extended_float: return "x86_extended_float";
	}
	panic("invalid mode_arithmetic");
}

286
287
/** 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)
288
{
Matthias Braun's avatar
Matthias Braun committed
289
290
	symbol_t key;
	key.str     = str;
291
	key.typetag = typetag;
292

Matthias Braun's avatar
Matthias Braun committed
293
294
	symbol_t *entry = set_find(symbol_t, symtbl, &key, sizeof(key),
	                           hash_str(str) + typetag * 17);
295
	return entry ? entry->code : SYMERROR;
296
297
}

298
void write_long(write_env_t *env, long value)
299
{
Matthias Braun's avatar
Matthias Braun committed
300
	fprintf(env->file, "%ld ", value);
301
302
}

303
void write_int(write_env_t *env, int value)
304
{
Matthias Braun's avatar
Matthias Braun committed
305
	fprintf(env->file, "%d ", value);
306
307
}

308
void write_unsigned(write_env_t *env, unsigned value)
309
{
Matthias Braun's avatar
Matthias Braun committed
310
	fprintf(env->file, "%u ", value);
311
312
}

313
void write_size_t(write_env_t *env, size_t value)
314
{
Matthias Braun's avatar
Matthias Braun committed
315
	ir_fprintf(env->file, "%zu ", value);
316
317
}

318
void write_symbol(write_env_t *env, const char *symbol)
319
{
Matthias Braun's avatar
Matthias Braun committed
320
321
	fputs(symbol, env->file);
	fputc(' ', env->file);
322
323
}

324
void write_entity_ref(write_env_t *env, ir_entity *entity)
325
326
327
328
{
	write_long(env, get_entity_nr(entity));
}

329
void write_type_ref(write_env_t *env, ir_type *type)
330
{
331
	switch (get_type_opcode(type)) {
332
	case tpo_unknown:
Matthias Braun's avatar
Matthias Braun committed
333
		write_symbol(env, "unknown");
334
335
		return;
	case tpo_code:
Matthias Braun's avatar
Matthias Braun committed
336
		write_symbol(env, "code");
337
338
339
		return;
	default:
		break;
Matthias Braun's avatar
Matthias Braun committed
340
	}
341
	write_long(env, get_type_nr(type));
342
343
}

344
void write_string(write_env_t *env, const char *string)
Matthias Braun's avatar
Matthias Braun committed
345
346
{
	fputc('"', env->file);
Matthias Braun's avatar
Matthias Braun committed
347
	for (const char *c = string; *c != '\0'; ++c) {
Matthias Braun's avatar
Matthias Braun committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
		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);
Matthias Braun's avatar
Matthias Braun committed
363
	fputc(' ', env->file);
Matthias Braun's avatar
Matthias Braun committed
364
365
}

366
void write_ident(write_env_t *env, ident *id)
Matthias Braun's avatar
Matthias Braun committed
367
368
369
370
{
	write_string(env, get_id_str(id));
}

371
void write_ident_null(write_env_t *env, ident *id)
Matthias Braun's avatar
Matthias Braun committed
372
373
374
375
376
377
378
379
{
	if (id == NULL) {
		fputs("NULL ", env->file);
	} else {
		write_ident(env, id);
	}
}

380
void write_mode_ref(write_env_t *env, ir_mode *mode)
381
{
382
	write_string(env, get_mode_name(mode));
383
384
}

385
void write_tarval_ref(write_env_t *env, ir_tarval *tv)
386
{
387
388
389
390
391
392
	ir_mode *mode = get_tarval_mode(tv);
	write_mode_ref(env, mode);
	char buf[128];
	const char *ascii = ir_tarval_to_ascii(buf, sizeof(buf), tv);
	fputs(ascii, env->file);
	fputc(' ', env->file);
393
394
}

395
void write_align(write_env_t *env, ir_align align)
396
397
398
399
400
{
	fputs(get_align_name(align), env->file);
	fputc(' ', env->file);
}

401
void write_builtin_kind(write_env_t *env, ir_builtin_kind kind)
402
{
403
	fputs(get_builtin_kind_name(kind), env->file);
404
405
406
	fputc(' ', env->file);
}

407
void write_cond_jmp_predicate(write_env_t *env, cond_jmp_predicate pred)
408
{
409
	fputs(get_cond_jmp_predicate_name(pred), env->file);
410
411
412
	fputc(' ', env->file);
}

413
void write_relation(write_env_t *env, ir_relation relation)
Matthias Braun's avatar
Matthias Braun committed
414
415
416
417
{
	write_long(env, (long)relation);
}

418
void write_throws(write_env_t *env, bool throws)
Matthias Braun's avatar
Matthias Braun committed
419
420
421
422
{
	write_symbol(env, throws ? "throw" : "nothrow");
}

423
void write_loop(write_env_t *env, bool loop)
424
425
426
427
{
	write_symbol(env, loop ? "loop" : "noloop");
}

Matthias Braun's avatar
Matthias Braun committed
428
static void write_list_begin(write_env_t *env)
429
430
431
432
{
	fputs("[", env->file);
}

Matthias Braun's avatar
Matthias Braun committed
433
static void write_list_end(write_env_t *env)
434
435
436
437
{
	fputs("] ", env->file);
}

Matthias Braun's avatar
Matthias Braun committed
438
439
440
441
442
443
444
445
446
447
static void write_scope_begin(write_env_t *env)
{
	fputs("{\n", env->file);
}

static void write_scope_end(write_env_t *env)
{
	fputs("}\n\n", env->file);
}

448
void write_node_ref(write_env_t *env, const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
449
450
451
452
{
	write_long(env, get_irn_node_nr(node));
}

453
454
void write_initializer(write_env_t *const env,
                       ir_initializer_t const *const ini)
455
456
457
{
	FILE *f = env->file;
	ir_initializer_kind_t ini_kind = get_initializer_kind(ini);
458

459
460
461
	fputs(get_initializer_kind_name(ini_kind), f);
	fputc(' ', f);

462
463
	switch (ini_kind) {
	case IR_INITIALIZER_CONST:
Matthias Braun's avatar
Matthias Braun committed
464
465
		write_node_ref(env, get_initializer_const_value(ini));
		return;
466

467
	case IR_INITIALIZER_TARVAL:
468
		write_tarval_ref(env, get_initializer_tarval_value(ini));
Matthias Braun's avatar
Matthias Braun committed
469
		return;
470

471
	case IR_INITIALIZER_NULL:
Matthias Braun's avatar
Matthias Braun committed
472
		return;
473

474
	case IR_INITIALIZER_COMPOUND: {
Matthias Braun's avatar
Matthias Braun committed
475
		size_t n = get_initializer_compound_n_entries(ini);
Matthias Braun's avatar
Matthias Braun committed
476
		write_size_t(env, n);
Matthias Braun's avatar
Matthias Braun committed
477
		for (size_t i = 0; i < n; ++i)
478
			write_initializer(env, get_initializer_compound_value(ini, i));
Matthias Braun's avatar
Matthias Braun committed
479
		return;
480
	}
481
	}
482
	panic("unknown initializer kind");
483
484
}

485
void write_pin_state(write_env_t *env, op_pin_state state)
486
{
Matthias Braun's avatar
Matthias Braun committed
487
	fputs(get_op_pin_state_name(state), env->file);
488
489
490
	fputc(' ', env->file);
}

491
void write_volatility(write_env_t *env, ir_volatility vol)
492
493
494
495
496
{
	fputs(get_volatility_name(vol), env->file);
	fputc(' ', env->file);
}

Matthias Braun's avatar
Matthias Braun committed
497
static void write_type_state(write_env_t *env, ir_type_state state)
498
{
Matthias Braun's avatar
Matthias Braun committed
499
500
501
	fputs(get_type_state_name(state), env->file);
	fputc(' ', env->file);
}
502

503
void write_visibility(write_env_t *env, ir_visibility visibility)
Matthias Braun's avatar
Matthias Braun committed
504
505
506
507
{
	fputs(get_visibility_name(visibility), env->file);
	fputc(' ', env->file);
}
508

Matthias Braun's avatar
Matthias Braun committed
509
510
511
512
513
static void write_mode_arithmetic(write_env_t *env, ir_mode_arithmetic arithmetic)
{
	fputs(get_mode_arithmetic_name(arithmetic), env->file);
	fputc(' ', env->file);
}
514

Matthias Braun's avatar
Matthias Braun committed
515
516
517
518
519
static void write_type_common(write_env_t *env, ir_type *tp)
{
	fputc('\t', env->file);
	write_symbol(env, "type");
	write_long(env, get_type_nr(tp));
520
	write_symbol(env, get_type_opcode_name(get_type_opcode(tp)));
Matthias Braun's avatar
Matthias Braun committed
521
522
523
524
525
	write_unsigned(env, get_type_size_bytes(tp));
	write_unsigned(env, get_type_alignment_bytes(tp));
	write_type_state(env, get_type_state(tp));
	write_unsigned(env, tp->flags);
}
526

sebastian.buchwald1's avatar
sebastian.buchwald1 committed
527
528
static void write_type(write_env_t *env, ir_type *tp);

529
530
531
532
533
534
535
536
537
538
539
540
541
static bool is_internal_mode(ir_mode *mode)
{
	return !mode_is_int(mode) && !mode_is_reference(mode)
	    && !mode_is_float(mode);
}

static bool is_default_mode(ir_mode *mode)
{
	/* some modes which are always available in libfirm */
	return mode == mode_b || mode == mode_X || mode == mode_BB
	    || mode == mode_T || mode == mode_ANY || mode == mode_BAD;
}

Matthias Braun's avatar
Matthias Braun committed
542
543
static void write_type_primitive(write_env_t *env, ir_type *tp)
{
544
545
546
547
548
	/* skip types for internal modes */
	ir_mode *mode = get_type_mode(tp);
	if (is_internal_mode(mode) && !is_default_mode(mode))
		return;

Matthias Braun's avatar
Matthias Braun committed
549
	write_type_common(env, tp);
550
	write_mode_ref(env, mode);
Matthias Braun's avatar
Matthias Braun committed
551
	fputc('\n', env->file);
552
553
}

Matthias Braun's avatar
Matthias Braun committed
554
static void write_type_compound(write_env_t *env, ir_type *tp)
555
{
Matthias Braun's avatar
Matthias Braun committed
556
	if (is_Class_type(tp)) {
557
		if (get_class_n_subtypes(tp) > 0 || get_class_n_supertypes(tp) > 0) {
sebastian.buchwald1's avatar
sebastian.buchwald1 committed
558
			/* sub/superclass export not implemented yet, it's unclear whether
Matthias Braun's avatar
Matthias Braun committed
559
560
561
			 * class types will stay in libfirm anyway */
			panic("can't export class types yet");
		}
562
	}
Matthias Braun's avatar
Matthias Braun committed
563
564
565
	write_type_common(env, tp);
	write_ident_null(env, get_compound_ident(tp));
	fputc('\n', env->file);
566

Matthias Braun's avatar
Matthias Braun committed
567
	for (size_t i = 0, n = get_compound_n_members(tp); i < n; ++i) {
Matthias Braun's avatar
Matthias Braun committed
568
		ir_entity *member = get_compound_member(tp, i);
569
		pdeq_putr(env->entity_queue, member);
570
	}
Matthias Braun's avatar
Matthias Braun committed
571
}
572

Matthias Braun's avatar
Matthias Braun committed
573
574
static void write_type_array(write_env_t *env, ir_type *tp)
{
Matthias Braun's avatar
Matthias Braun committed
575
	ir_type *element_type = get_array_element_type(tp);
Matthias Braun's avatar
Matthias Braun committed
576
577
578
	write_type(env, element_type);

	write_type_common(env, tp);
Matthias Braun's avatar
Matthias Braun committed
579
	write_type_ref(env, element_type);
580
581
	ir_node *size = get_array_size(tp);
	if (is_Const(size))
582
		write_long(env, get_Const_long(size));
583
584
585
	else if (is_Unknown(size))
		write_symbol(env, "unknown");
	else
586
		panic("upper array bound is not constant");
Matthias Braun's avatar
Matthias Braun committed
587
588
	fputc('\n', env->file);
}
589

Matthias Braun's avatar
Matthias Braun committed
590
591
592
static void write_type_method(write_env_t *env, ir_type *tp)
{
	size_t nparams  = get_method_n_params(tp);
Matthias Braun's avatar
Matthias Braun committed
593
	for (size_t i = 0; i < nparams; i++)
Matthias Braun's avatar
Matthias Braun committed
594
		write_type(env, get_method_param_type(tp, i));
Matthias Braun's avatar
Matthias Braun committed
595
596
	size_t nresults = get_method_n_ress(tp);
	for (size_t i = 0; i < nresults; i++)
Matthias Braun's avatar
Matthias Braun committed
597
598
599
600
601
602
603
		write_type(env, get_method_res_type(tp, i));

	write_type_common(env, tp);
	write_unsigned(env, get_method_calling_convention(tp));
	write_unsigned(env, get_method_additional_properties(tp));
	write_size_t(env, nparams);
	write_size_t(env, nresults);
Matthias Braun's avatar
Matthias Braun committed
604
	for (size_t i = 0; i < nparams; i++)
Matthias Braun's avatar
Matthias Braun committed
605
		write_type_ref(env, get_method_param_type(tp, i));
Matthias Braun's avatar
Matthias Braun committed
606
	for (size_t i = 0; i < nresults; i++)
Matthias Braun's avatar
Matthias Braun committed
607
		write_type_ref(env, get_method_res_type(tp, i));
608
	write_unsigned(env, is_method_variadic(tp));
Matthias Braun's avatar
Matthias Braun committed
609
610
	fputc('\n', env->file);
}
611

Matthias Braun's avatar
Matthias Braun committed
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
static void write_type_pointer(write_env_t *env, ir_type *tp)
{
	ir_type *points_to = get_pointer_points_to_type(tp);

	write_type(env, points_to);

	write_type_common(env, tp);
	write_type_ref(env, points_to);
	fputc('\n', env->file);
}

static void write_type(write_env_t *env, ir_type *tp)
{
	if (type_visited(tp))
		return;
	mark_type_visited(tp);

629
	switch (get_type_opcode(tp)) {
Matthias Braun's avatar
Matthias Braun committed
630
631
632
633
634
635
636
637
638
	case tpo_unknown:
	case tpo_code:
	case tpo_uninitialized:
		/* no need to write special builtin types */
		return;

	case tpo_union:
	case tpo_struct:
	case tpo_class:
639
	case tpo_segment:
Matthias Braun's avatar
Matthias Braun committed
640
641
642
		write_type_compound(env, tp);
		return;

643
644
645
646
	case tpo_primitive: write_type_primitive(env, tp); return;
	case tpo_method:    write_type_method(env, tp);    return;
	case tpo_pointer:   write_type_pointer(env, tp);   return;
	case tpo_array:     write_type_array(env, tp);     return;
647
	}
648
	panic("can't write invalid type %+F", tp);
649
650
}

Matthias Braun's avatar
Matthias Braun committed
651
static void write_entity(write_env_t *env, ir_entity *ent)
652
{
Matthias Braun's avatar
Matthias Braun committed
653
	ir_type       *type       = get_entity_type(ent);
654
655
656
	ir_type       *owner      = get_entity_owner(ent);
	ir_visibility  visibility = get_entity_visibility(ent);
	ir_linkage     linkage    = get_entity_linkage(ent);
657

Matthias Braun's avatar
Matthias Braun committed
658
	if (entity_visited(ent))
659
		return;
Matthias Braun's avatar
Matthias Braun committed
660
	mark_entity_visited(ent);
661

Matthias Braun's avatar
Matthias Braun committed
662
663
	write_type(env, type);
	write_type(env, owner);
664
665
666
667
	if (is_alias_entity(ent)) {
		ir_entity *aliased = get_entity_alias(ent);
		write_entity(env, aliased);
	}
Matthias Braun's avatar
Matthias Braun committed
668
669
670

	fputc('\t', env->file);
	switch ((ir_entity_kind)ent->entity_kind) {
671
	case IR_ENTITY_ALIAS:           write_symbol(env, "alias");           break;
Matthias Braun's avatar
Matthias Braun committed
672
673
674
675
676
	case IR_ENTITY_NORMAL:          write_symbol(env, "entity");          break;
	case IR_ENTITY_METHOD:          write_symbol(env, "method");          break;
	case IR_ENTITY_LABEL:           write_symbol(env, "label");           break;
	case IR_ENTITY_COMPOUND_MEMBER: write_symbol(env, "compound_member"); break;
	case IR_ENTITY_PARAMETER:       write_symbol(env, "parameter");       break;
677
678
679
680
	case IR_ENTITY_UNKNOWN:
		write_symbol(env, "unknown");
		write_long(env, get_entity_nr(ent));
		return;
681
	}
Matthias Braun's avatar
Matthias Braun committed
682
	write_long(env, get_entity_nr(ent));
683

Matthias Braun's avatar
Matthias Braun committed
684
	if (ent->entity_kind != IR_ENTITY_LABEL
Matthias Braun's avatar
Matthias Braun committed
685
	 && ent->entity_kind != IR_ENTITY_PARAMETER) {
Matthias Braun's avatar
Matthias Braun committed
686
687
688
689
690
691
		write_ident_null(env, get_entity_ident(ent));
		if (!entity_has_ld_ident(ent)) {
			write_ident_null(env, NULL);
		} else {
			write_ident_null(env, get_entity_ld_ident(ent));
		}
692
	}
Matthias Braun's avatar
Matthias Braun committed
693
694
695

	write_visibility(env, visibility);
	write_list_begin(env);
696
	if (linkage & IR_LINKAGE_CONSTANT)
Matthias Braun's avatar
Matthias Braun committed
697
		write_symbol(env, "constant");
698
	if (linkage & IR_LINKAGE_WEAK)
Matthias Braun's avatar
Matthias Braun committed
699
		write_symbol(env, "weak");
700
	if (linkage & IR_LINKAGE_GARBAGE_COLLECT)
Matthias Braun's avatar
Matthias Braun committed
701
		write_symbol(env, "garbage_collect");
702
	if (linkage & IR_LINKAGE_MERGE)
Matthias Braun's avatar
Matthias Braun committed
703
		write_symbol(env, "merge");
704
	if (linkage & IR_LINKAGE_HIDDEN_USER)
Matthias Braun's avatar
Matthias Braun committed
705
706
707
708
709
710
711
712
713
		write_symbol(env, "hidden_user");
	write_list_end(env);

	write_type_ref(env, type);
	if (ent->entity_kind != IR_ENTITY_LABEL)
		write_type_ref(env, owner);
	write_volatility(env, get_entity_volatility(ent));

	switch ((ir_entity_kind)ent->entity_kind) {
714
715
716
	case IR_ENTITY_ALIAS:
		write_entity_ref(env, get_entity_alias(ent));
		break;
717
718
719
720

	case IR_ENTITY_NORMAL: {
		ir_initializer_t const *const init = get_entity_initializer(ent);
		if (init) {
Matthias Braun's avatar
Matthias Braun committed
721
			write_symbol(env, "initializer");
722
			write_initializer(env, init);
Matthias Braun's avatar
Matthias Braun committed
723
724
		} else {
			write_symbol(env, "none");
725
		}
Matthias Braun's avatar
Matthias Braun committed
726
		break;
727
728
	}

Matthias Braun's avatar
Matthias Braun committed
729
730
	case IR_ENTITY_COMPOUND_MEMBER:
		write_long(env, get_entity_offset(ent));
731
732
		write_unsigned(env, get_entity_bitfield_offset(ent));
		write_unsigned(env, get_entity_bitfield_size(ent));
Matthias Braun's avatar
Matthias Braun committed
733
734
735
736
737
738
739
740
		break;
	case IR_ENTITY_PARAMETER: {
		size_t num = get_entity_parameter_number(ent);
		if (num == IR_VA_START_PARAMETER_NUMBER) {
			write_symbol(env, "va_start");
		} else {
			write_size_t(env, num);
		}
741
742
743
		write_long(env, get_entity_offset(ent));
		write_unsigned(env, get_entity_bitfield_offset(ent));
		write_unsigned(env, get_entity_bitfield_size(ent));
Matthias Braun's avatar
Matthias Braun committed
744
745
		break;
	}
746
747
748
	case IR_ENTITY_METHOD:
		write_long(env, (long)get_entity_additional_properties(ent));
		break;
749
	case IR_ENTITY_UNKNOWN:
Matthias Braun's avatar
Matthias Braun committed
750
751
	case IR_ENTITY_LABEL:
		break;
752
753
754
	}

	fputc('\n', env->file);
755
756
}

757
void write_switch_table_ref(write_env_t *env, const ir_switch_table *table)
758
{
Matthias Braun's avatar
Matthias Braun committed
759
760
	size_t n_entries = ir_switch_table_get_n_entries(table);
	write_size_t(env, n_entries);
Matthias Braun's avatar
Matthias Braun committed
761
	for (size_t i = 0; i < n_entries; ++i) {
Matthias Braun's avatar
Matthias Braun committed
762
763
764
765
		long       pn  = ir_switch_table_get_pn(table, i);
		ir_tarval *min = ir_switch_table_get_min(table, i);
		ir_tarval *max = ir_switch_table_get_max(table, i);
		write_long(env, pn);
766
767
		write_tarval_ref(env, min);
		write_tarval_ref(env, max);
Matthias Braun's avatar
Matthias Braun committed
768
	}
769
770
}

771
void write_pred_refs(write_env_t *env, const ir_node *node, int from)
772
{
Matthias Braun's avatar
Matthias Braun committed
773
	write_list_begin(env);
Matthias Braun's avatar
Matthias Braun committed
774
	int arity = get_irn_arity(node);
Matthias Braun's avatar
Matthias Braun committed
775
	assert(from <= arity);
Matthias Braun's avatar
Matthias Braun committed
776
	for (int i = from; i < arity; ++i) {
Matthias Braun's avatar
Matthias Braun committed
777
778
		ir_node *pred = get_irn_n(node, i);
		write_node_ref(env, pred);
779
	}
Matthias Braun's avatar
Matthias Braun committed
780
	write_list_end(env);
781
782
}

783
void write_node_nr(write_env_t *env, const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
784
785
786
787
788
{
	write_long(env, get_irn_node_nr(node));
}

static void write_ASM(write_env_t *env, const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
789
{
Matthias Braun's avatar
Matthias Braun committed
790
791
792
	write_symbol(env, "ASM");
	write_node_nr(env, node);
	write_node_nr(env, get_nodes_block(node));
793
	write_node_nr(env, get_ASM_mem(node));
Matthias Braun's avatar
Matthias Braun committed
794
795
796

	write_ident(env, get_ASM_text(node));
	write_list_begin(env);
797
798
799
	ir_asm_constraint *input_constraints = get_ASM_input_constraints(node);
	int                n_inputs          = get_ASM_n_inputs(node);
	for (int i = 0; i < n_inputs; ++i) {
Matthias Braun's avatar
Matthias Braun committed
800
801
802
		const ir_asm_constraint *constraint = &input_constraints[i];
		write_unsigned(env, constraint->pos);
		write_ident(env, constraint->constraint);
Matthias Braun's avatar
Matthias Braun committed
803
		write_mode_ref(env, constraint->mode);
Matthias Braun's avatar
Matthias Braun committed
804
805
806
807
	}
	write_list_end(env);

	write_list_begin(env);
808
809
810
	ir_asm_constraint *output_constraints  = get_ASM_output_constraints(node);
	size_t            n_output_constraints = get_ASM_n_output_constraints(node);
	for (size_t i = 0; i < n_output_constraints; ++i) {
Matthias Braun's avatar
Matthias Braun committed
811
812
813
		const ir_asm_constraint *constraint = &output_constraints[i];
		write_unsigned(env, constraint->pos);
		write_ident(env, constraint->constraint);
Matthias Braun's avatar
Matthias Braun committed
814
		write_mode_ref(env, constraint->mode);
Matthias Braun's avatar
Matthias Braun committed
815
816
817
818
	}
	write_list_end(env);

	write_list_begin(env);
819
820
821
	ident **clobbers   = get_ASM_clobbers(node);
	size_t  n_clobbers = get_ASM_n_clobbers(node);
	for (size_t i = 0; i < n_clobbers; ++i) {
Matthias Braun's avatar
Matthias Braun committed
822
823
824
825
		ident *clobber = clobbers[i];
		write_ident(env, clobber);
	}
	write_list_end(env);
Matthias Braun's avatar
Matthias Braun committed
826
827

	write_pin_state(env, get_irn_pinned(node));
Matthias Braun's avatar
Matthias Braun committed
828
	write_pred_refs(env, node, n_ASM_max+1);
Matthias Braun's avatar
Matthias Braun committed
829
830
}

Matthias Braun's avatar
Matthias Braun committed
831
static void write_Phi(write_env_t *env, const ir_node *node)
832
{
Matthias Braun's avatar
Matthias Braun committed
833
834
835
836
	write_symbol(env, "Phi");
	write_node_nr(env, node);
	write_node_ref(env, get_nodes_block(node));
	write_mode_ref(env, get_irn_mode(node));
837
	write_loop(env, get_Phi_loop(node));
Matthias Braun's avatar
Matthias Braun committed
838
839
	write_pred_refs(env, node, 0);
}
840

Matthias Braun's avatar
Matthias Braun committed
841
842
843
static void write_Block(write_env_t *env, const ir_node *node)
{
	ir_entity *entity = get_Block_entity(node);
844

Matthias Braun's avatar
Matthias Braun committed
845
846
847
848
849
850
851
	if (entity != NULL) {
		write_symbol(env, "BlockL");
		write_node_nr(env, node);
		write_entity_ref(env, entity);
	} else {
		write_symbol(env, "Block");
		write_node_nr(env, node);
852
	}
Matthias Braun's avatar
Matthias Braun committed
853
854
	write_pred_refs(env, node, 0);
}
855

Matthias Braun's avatar
Matthias Braun committed
856
857
858
859
860
861
862
static void write_Anchor(write_env_t *env, const ir_node *node)
{
	write_symbol(env, "Anchor");
	write_node_nr(env, node);
	write_pred_refs(env, node, 0);
}

863
void register_node_writer(ir_op *op, write_node_func *func)
Matthias Braun's avatar
Matthias Braun committed
864
{
865
	set_generic_function_ptr(op, func);
Matthias Braun's avatar
Matthias Braun committed
866
867
868
869
}

static void writers_init(void)
{
Matthias Braun's avatar
Matthias Braun committed
870
	ir_clear_opcodes_generic_func();
871
872
873
874
	register_node_writer(op_Anchor, write_Anchor);
	register_node_writer(op_ASM,    write_ASM);
	register_node_writer(op_Block,  write_Block);
	register_node_writer(op_Phi,    write_Phi);
Matthias Braun's avatar
Matthias Braun committed
875
876
877
878
879
	register_generated_node_writers();
}

static void write_node(const ir_node *node, write_env_t *env)
{
880
881
	ir_op           *const op   = get_irn_op(node);
	write_node_func *const func = get_generic_function_ptr(write_node_func, op);
Matthias Braun's avatar
Matthias Braun committed
882
883
884

	fputc('\t', env->file);
	if (func == NULL)
885
		panic("no write_node_func for %+F", node);
Matthias Braun's avatar
Matthias Braun committed
886
887
888
889
890
891
892
893
	func(env, node);
	fputc('\n', env->file);
}

static void write_node_recursive(ir_node *node, write_env_t *env);

static void write_preds(ir_node *node, write_env_t *env)
{
894
	foreach_irn_in(node, i, pred) {
Matthias Braun's avatar
Matthias Braun committed
895
		write_node_recursive(pred, env);
896
	}
Matthias Braun's avatar
Matthias Braun committed
897
}
898

Matthias Braun's avatar
Matthias Braun committed
899
900
901
902
903
904
905
906
907
908
909
/**
 * Recursively write nodes.
 * The reader expects nodes in a way that except for block/phi/anchor nodes
 * all predecessors are already defined when we reach them. So usually we
 * recurse to all our predecessors except for block/phi/anchor nodes where
 * we put the predecessors into a queue for later processing.
 */
static void write_node_recursive(ir_node *node, write_env_t *env)
{
	if (irn_visited_else_mark(node))
		return;
910

Matthias Braun's avatar
Matthias Braun committed
911
912
913
914
915
916
917
	if (!is_Block(node)) {
		write_node_recursive(get_nodes_block(node), env);
	}
	/* write predecessors */
	if (!is_Phi(node) && !is_Block(node) && !is_Anchor(node)) {
		write_preds(node, env);
	} else {
918
		foreach_irn_in(node, i, pred) {
Matthias Braun's avatar
Matthias Braun committed
919
920
921
922
923
924
925
926
927
928
929
930
931
			pdeq_putr(env->write_queue, pred);
		}
	}
	write_node(node, env);
}

static void write_mode(write_env_t *env, ir_mode *mode)
{
	if (mode_is_int(mode)) {
		write_symbol(env, "int_mode");
		write_string(env, get_mode_name(mode));
		write_mode_arithmetic(env, get_mode_arithmetic(mode));
		write_unsigned(env, get_mode_size_bits(mode));
932
		write_int(env, mode_is_signed(mode));
Matthias Braun's avatar
Matthias Braun committed
933
934
935
936
937
938
939
940
		write_unsigned(env, get_mode_modulo_shift(mode));
	} else if (mode_is_reference(mode)) {
		write_symbol(env, "reference_mode");
		write_string(env, get_mode_name(mode));
		write_mode_arithmetic(env, get_mode_arithmetic(mode));
		write_unsigned(env, get_mode_size_bits(mode));
		write_unsigned(env, get_mode_modulo_shift(mode));

941
		write_mode_ref(env, get_reference_offset_mode(mode));
Matthias Braun's avatar
Matthias Braun committed
942
943
944
945
946
947
948
		write_int(env, (mode == mode_P ? 1 : 0));
	} else if (mode_is_float(mode)) {
		write_symbol(env, "float_mode");
		write_string(env, get_mode_name(mode));
		write_mode_arithmetic(env, get_mode_arithmetic(mode));
		write_unsigned(env, get_mode_exponent_size(mode));
		write_unsigned(env, get_mode_mantissa_size(mode));
949
		write_unsigned(env, get_mode_float_int_overflow(mode));
Matthias Braun's avatar
Matthias Braun committed
950
	} else {
951
		panic("cannot write internal modes");
952
	}
953
954
}

Matthias Braun's avatar
Matthias Braun committed
955
static void write_modes(write_env_t *env)
956
{
Matthias Braun's avatar
Matthias Braun committed
957
958
	write_symbol(env, "modes");
	fputs("{\n", env->file);
959

Matthias Braun's avatar
Matthias Braun committed
960
	for (size_t i = 0, n_modes = ir_get_n_modes(); i < n_modes; i++) {
Matthias Braun's avatar
Matthias Braun committed
961
		ir_mode *mode = ir_get_mode(i);
962
963
		if (is_internal_mode(mode))
			continue;
Matthias Braun's avatar
Matthias Braun committed
964
965
		fputc('\t', env->file);
		write_mode(env, mode);
966
967
968
		fputc('\n', env->file);
	}

Matthias Braun's avatar
Matthias Braun committed
969
	fputs("}\n\n", env->file);
970
971
}

Matthias Braun's avatar
Matthias Braun committed
972
static void write_program(write_env_t *env)
973
{
Matthias Braun's avatar
Matthias Braun committed
974
975
	write_symbol(env, "program");
	write_scope_begin(env);
976
	if (irp_prog_name_is_set()) {
Matthias Braun's avatar
Matthias Braun committed
977
978
		fputc('\t', env->file);
		write_symbol(env, "name");
Matthias Braun's avatar
Matthias Braun committed
979
		write_string(env, get_irp_name());
Matthias Braun's avatar
Matthias Braun committed
980
		fputc('\n', env->file);
981
982
	}

Matthias Braun's avatar
Matthias Braun committed
983
	for (ir_segment_t s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
984
		ir_type *segment_type = get_segment_type(s);
Matthias Braun's avatar
Matthias Braun committed
985
986
987
		fputc('\t', env->file);
		write_symbol(env, "segment_type");
		write_symbol(env, get_segment_name(s));
<