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
COMPILETIME_ASSERT(ir_bk_va_arg == ir_bk_last, complete_builtin_list);

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

139
	symtbl = new_set(symbol_cmp, 256);
140

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

#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);
156
	INSERT(tt_tpo, "segment", tpo_segment);
157
158
159
160
161
162
163
164
	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
165
	INSERT(tt_segment, "jcr", IR_SEGMENT_JCR);
166

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

173
174
175
	INSERT(tt_loop, "loop",   true);
	INSERT(tt_loop, "noloop", false);

176
177
178
179
180
	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);
181

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

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

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

Matthias Braun's avatar
Matthias Braun committed
208
209
210
211
212
213
214
215
216
217
218
219
220
	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);
221
	INSERTENUM(tt_builtin_kind, ir_bk_saturating_increment);
222
	INSERTENUM(tt_builtin_kind, ir_bk_compare_swap);
Manuel Mohr's avatar
Manuel Mohr committed
223
224
225
	INSERTENUM(tt_builtin_kind, ir_bk_may_alias);
	INSERTENUM(tt_builtin_kind, ir_bk_va_start);
	INSERTENUM(tt_builtin_kind, ir_bk_va_arg);
226
227
228
229
230
231
232
233
234
235

	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
236
237
238
239
240
	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);

241
242
243
244
245
246
247
248
249
250
	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);

251
#undef INSERTKEYWORD
252
253
254
255
#undef INSERTENUM
#undef INSERT
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

464
465
466
	fputs(get_initializer_kind_name(ini_kind), f);
	fputc(' ', f);

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

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

476
	case IR_INITIALIZER_NULL:
Matthias Braun's avatar
Matthias Braun committed
477
		return;
478

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

685
	if (ent->kind != IR_ENTITY_LABEL && ent->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
		write_symbol(env, "hidden_user");
	write_list_end(env);

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

713
	switch ((ir_entity_kind)ent->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
	case IR_ENTITY_LABEL:
751
	case IR_ENTITY_SPILLSLOT:
Matthias Braun's avatar
Matthias Braun committed
752
		break;
753
754
755
	}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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