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);
Manuel Mohr's avatar
Manuel Mohr committed
221
222
223
	INSERTENUM(tt_builtin_kind, ir_bk_may_alias);
	INSERTENUM(tt_builtin_kind, ir_bk_va_start);
	INSERTENUM(tt_builtin_kind, ir_bk_va_arg);
224
225
226
227
228
229
230
231
232
233

	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
234
235
236
237
238
	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);

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_type_state, layout_undefined);
	INSERTENUM(tt_type_state, layout_fixed);

	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
256
257
258
259
260
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
261
	case IR_SEGMENT_JCR:          return "jcr";
262
	}
263
	panic("invalid segment");
264
265
}

266
267
268
static const char *get_visibility_name(ir_visibility visibility)
{
	switch (visibility) {
269
270
271
272
273
	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";
274
	}
275
	panic("invalid visibility");
Matthias Braun's avatar
Matthias Braun committed
276
277
278
279
280
281
282
283
284
285
286
287
288
}

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

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

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

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

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

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

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

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

327
void write_entity_ref(write_env_t *env, ir_entity *entity)
328
329
330
331
{
	write_long(env, get_entity_nr(entity));
}

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

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

369
void write_ident(write_env_t *env, ident *id)
Matthias Braun's avatar
Matthias Braun committed
370
371
372
373
{
	write_string(env, get_id_str(id));
}

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

383
void write_mode_ref(write_env_t *env, ir_mode *mode)
384
{
385
	write_string(env, get_mode_name(mode));
386
387
}

388
void write_tarval_ref(write_env_t *env, ir_tarval *tv)
389
{
390
391
392
393
394
395
	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);
396
397
}

398
void write_align(write_env_t *env, ir_align align)
399
400
401
402
403
{
	fputs(get_align_name(align), env->file);
	fputc(' ', env->file);
}

404
void write_builtin_kind(write_env_t *env, ir_builtin_kind kind)
405
{
406
	fputs(get_builtin_kind_name(kind), env->file);
407
408
409
	fputc(' ', env->file);
}

410
void write_cond_jmp_predicate(write_env_t *env, cond_jmp_predicate pred)
411
{
412
	fputs(get_cond_jmp_predicate_name(pred), env->file);
413
414
415
	fputc(' ', env->file);
}

416
void write_relation(write_env_t *env, ir_relation relation)
Matthias Braun's avatar
Matthias Braun committed
417
418
419
420
{
	write_long(env, (long)relation);
}

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

426
void write_loop(write_env_t *env, bool loop)
427
428
429
430
{
	write_symbol(env, loop ? "loop" : "noloop");
}

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

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

Matthias Braun's avatar
Matthias Braun committed
441
442
443
444
445
446
447
448
449
450
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);
}

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

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

462
463
464
	fputs(get_initializer_kind_name(ini_kind), f);
	fputc(' ', f);

465
466
	switch (ini_kind) {
	case IR_INITIALIZER_CONST:
Matthias Braun's avatar
Matthias Braun committed
467
468
		write_node_ref(env, get_initializer_const_value(ini));
		return;
469

470
	case IR_INITIALIZER_TARVAL:
471
		write_tarval_ref(env, get_initializer_tarval_value(ini));
Matthias Braun's avatar
Matthias Braun committed
472
		return;
473

474
	case IR_INITIALIZER_NULL:
Matthias Braun's avatar
Matthias Braun committed
475
		return;
476

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

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

494
void write_volatility(write_env_t *env, ir_volatility vol)
495
496
497
498
499
{
	fputs(get_volatility_name(vol), env->file);
	fputc(' ', env->file);
}

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

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

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

Matthias Braun's avatar
Matthias Braun committed
518
519
520
521
522
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));
523
	write_symbol(env, get_type_opcode_name(get_type_opcode(tp)));
524
525
	write_unsigned(env, get_type_size(tp));
	write_unsigned(env, get_type_alignment(tp));
Matthias Braun's avatar
Matthias Braun committed
526
527
528
	write_type_state(env, get_type_state(tp));
	write_unsigned(env, tp->flags);
}
529

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

532
533
534
535
536
537
538
539
540
541
542
543
544
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
545
546
static void write_type_primitive(write_env_t *env, ir_type *tp)
{
547
548
549
550
551
	/* 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
552
	write_type_common(env, tp);
553
	write_mode_ref(env, mode);
Matthias Braun's avatar
Matthias Braun committed
554
	fputc('\n', env->file);
555
556
}

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

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

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

	write_type_common(env, tp);
Matthias Braun's avatar
Matthias Braun committed
582
	write_type_ref(env, element_type);
Christoph Mallon's avatar
Christoph Mallon committed
583
	write_unsigned(env, get_array_size(tp));
Matthias Braun's avatar
Matthias Braun committed
584
585
	fputc('\n', env->file);
}
586

Matthias Braun's avatar
Matthias Braun committed
587
588
589
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
590
	for (size_t i = 0; i < nparams; i++)
Matthias Braun's avatar
Matthias Braun committed
591
		write_type(env, get_method_param_type(tp, i));
Matthias Braun's avatar
Matthias Braun committed
592
593
	size_t nresults = get_method_n_ress(tp);
	for (size_t i = 0; i < nresults; i++)
Matthias Braun's avatar
Matthias Braun committed
594
595
596
597
598
599
600
		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);
601
	write_unsigned(env, is_method_variadic(tp));
Matthias Braun's avatar
Matthias Braun committed
602
	for (size_t i = 0; i < nparams; i++)
Matthias Braun's avatar
Matthias Braun committed
603
		write_type_ref(env, get_method_param_type(tp, i));
Matthias Braun's avatar
Matthias Braun committed
604
	for (size_t i = 0; i < nresults; i++)
Matthias Braun's avatar
Matthias Braun committed
605
606
607
		write_type_ref(env, get_method_res_type(tp, i));
	fputc('\n', env->file);
}
608

Matthias Braun's avatar
Matthias Braun committed
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
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);

626
	switch (get_type_opcode(tp)) {
Matthias Braun's avatar
Matthias Braun committed
627
628
629
630
631
632
633
634
635
	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:
636
	case tpo_segment:
Matthias Braun's avatar
Matthias Braun committed
637
638
639
		write_type_compound(env, tp);
		return;

640
641
642
643
	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;
644
	}
645
	panic("can't write invalid type %+F", tp);
646
647
}

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

Matthias Braun's avatar
Matthias Braun committed
655
	if (entity_visited(ent))
656
		return;
Matthias Braun's avatar
Matthias Braun committed
657
	mark_entity_visited(ent);
658

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

	fputc('\t', env->file);
667
	switch ((ir_entity_kind)ent->kind) {
668
	case IR_ENTITY_ALIAS:           write_symbol(env, "alias");           break;
Matthias Braun's avatar
Matthias Braun committed
669
670
671
672
673
	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;
674
675
676
677
	case IR_ENTITY_UNKNOWN:
		write_symbol(env, "unknown");
		write_long(env, get_entity_nr(ent));
		return;
678
679
	case IR_ENTITY_SPILLSLOT:
		panic("Unexpected entity %+F", ent); // Should only exist in backend
680
	}
Matthias Braun's avatar
Matthias Braun committed
681
	write_long(env, get_entity_nr(ent));
682

683
	if (ent->kind != IR_ENTITY_LABEL && ent->kind != IR_ENTITY_PARAMETER) {
Matthias Braun's avatar
Matthias Braun committed
684
685
686
687
688
689
		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));
		}
690
	}
Matthias Braun's avatar
Matthias Braun committed
691
692
693

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

	write_type_ref(env, type);
707
	if (ent->kind != IR_ENTITY_LABEL)
Matthias Braun's avatar
Matthias Braun committed
708
709
710
		write_type_ref(env, owner);
	write_volatility(env, get_entity_volatility(ent));

711
	switch ((ir_entity_kind)ent->kind) {
712
713
714
	case IR_ENTITY_ALIAS:
		write_entity_ref(env, get_entity_alias(ent));
		break;
715
716
717
718

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

Matthias Braun's avatar
Matthias Braun committed
727
728
	case IR_ENTITY_COMPOUND_MEMBER:
		write_long(env, get_entity_offset(ent));
729
730
		write_unsigned(env, get_entity_bitfield_offset(ent));
		write_unsigned(env, get_entity_bitfield_size(ent));
Matthias Braun's avatar
Matthias Braun committed
731
732
733
734
735
736
737
738
		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);
		}
739
740
741
		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
742
743
		break;
	}
744
745
746
	case IR_ENTITY_METHOD:
		write_long(env, (long)get_entity_additional_properties(ent));
		break;
747
	case IR_ENTITY_UNKNOWN:
Matthias Braun's avatar
Matthias Braun committed
748
	case IR_ENTITY_LABEL:
749
	case IR_ENTITY_SPILLSLOT:
Matthias Braun's avatar
Matthias Braun committed
750
		break;
751
752
753
	}

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

756
void write_switch_table_ref(write_env_t *env, const ir_switch_table *table)
757
{
Matthias Braun's avatar
Matthias Braun committed
758
759
	size_t n_entries = ir_switch_table_get_n_entries(table);
	write_size_t(env, n_entries);
Matthias Braun's avatar
Matthias Braun committed
760
	for (size_t i = 0; i < n_entries; ++i) {
Matthias Braun's avatar
Matthias Braun committed
761
762
763
764
		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);
765
766
		write_tarval_ref(env, min);
		write_tarval_ref(env, max);
Matthias Braun's avatar
Matthias Braun committed
767
	}
768
769
}

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

782
void write_node_nr(write_env_t *env, const ir_node *node)
Matthias Braun's avatar
Matthias Braun committed
783
784
785
786
787
{
	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
788
{
Matthias Braun's avatar
Matthias Braun committed
789
790
791
	write_symbol(env, "ASM");
	write_node_nr(env, node);
	write_node_nr(env, get_nodes_block(node));
792
	write_node_nr(env, get_ASM_mem(node));
Matthias Braun's avatar
Matthias Braun committed
793
794
795

	write_ident(env, get_ASM_text(node));
	write_list_begin(env);
796
797
798
	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
799
800
801
		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
802
		write_mode_ref(env, constraint->mode);
Matthias Braun's avatar
Matthias Braun committed
803
804
805
806
	}
	write_list_end(env);

	write_list_begin(env);
807
808
809
	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
810
811
812
		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
813
		write_mode_ref(env, constraint->mode);
Matthias Braun's avatar
Matthias Braun committed
814
815
816
817
	}
	write_list_end(env);

	write_list_begin(env);
818
819
820
	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
821
822
823
824
		ident *clobber = clobbers[i];
		write_ident(env, clobber);
	}
	write_list_end(env);
Matthias Braun's avatar
Matthias Braun committed
825
826

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

Matthias Braun's avatar
Matthias Braun committed
830
static void write_Phi(write_env_t *env, const ir_node *node)
831
{
Matthias Braun's avatar
Matthias Braun committed
832
833
834
835
	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));
836
	write_loop(env, get_Phi_loop(node));
Matthias Braun's avatar
Matthias Braun committed
837
838
	write_pred_refs(env, node, 0);
}
839

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

Matthias Braun's avatar
Matthias Braun committed
844
845
846
847
848
849
850
	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);
851
	}
Matthias Braun's avatar
Matthias Braun committed
852
853
	write_pred_refs(env, node, 0);
}
854

Matthias Braun's avatar
Matthias Braun committed
855
856
857
858
859
860
861
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);
}

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

static void writers_init(void)
{
Matthias Braun's avatar
Matthias Braun committed
869
	ir_clear_opcodes_generic_func();
870
871
872
873
	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
874
875
876
877
878
	register_generated_node_writers();
}

static void write_node(const ir_node *node, write_env_t *env)
{
879
880
	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
881
882
883

	fputc('\t', env->file);
	if (func == NULL)
884
		panic("no write_node_func for %+F", node);
Matthias Braun's avatar
Matthias Braun committed
885
886
887
888
889
890
891
892
	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)
{
893
	foreach_irn_in(node, i, pred) {
Matthias Braun's avatar
Matthias Braun committed
894
		write_node_recursive(pred, env);
895
	}
Matthias Braun's avatar
Matthias Braun committed
896
}
897

Matthias Braun's avatar
Matthias Braun committed
898
899
900
901
902
903
904
905
906
907
908
/**
 * 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;
909

Matthias Braun's avatar
Matthias Braun committed
910
911
912
913
914
915
916
	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 {
917
		foreach_irn_in(node, i, pred) {
Matthias Braun's avatar
Matthias Braun committed
918
919
920
921
922
923
924
925
926
927
928
929
930
			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));
931
		write_int(env, mode_is_signed(mode));
Matthias Braun's avatar
Matthias Braun committed
932
933
934
935
936
937
938
939
		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));

940
		write_mode_ref(env, get_reference_offset_mode(mode));
Matthias Braun's avatar
Matthias Braun committed
941
942
943
944
945
946
947
		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));
948
		write_unsigned(env, get_mode_float_int_overflow(mode));
Matthias Braun's avatar
Matthias Braun committed
949
	} else {
950
		panic("cannot write internal modes");
951
	}
952
953
}

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

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

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

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