99ff27f43f2cd02e68dfab47f1244eea4a00b5b7
[libfirm] / ir / ir / irio.c
1 /*
2  * Copyright (C) 1995-2009 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Write textual representation of firm to file.
23  * @author  Moritz Kroll
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include <string.h>
29
30 #include "irio.h"
31
32 #include "irprog.h"
33 #include "irgraph_t.h"
34 #include "ircons.h"
35 #include "irgmod.h"
36 #include "irflag_t.h"
37 #include "irgwalk.h"
38 #include "tv.h"
39 #include "array.h"
40 #include "error.h"
41 #include "adt/set.h"
42
43 #define LEXERROR ((unsigned) ~0)
44
45 typedef struct io_env
46 {
47         FILE *file;
48         set *idset;               /**< id_entry set, which maps from file ids to new Firm elements */
49         int ignoreblocks;
50         int line, col;
51         ir_type **fixedtypes;
52 } io_env_t;
53
54 typedef enum typetag_t
55 {
56         tt_iro,
57         tt_tpo,
58         tt_align,
59         tt_allocation,
60         tt_peculiarity,
61         tt_pin_state,
62         tt_type_state,
63         tt_variability,
64         tt_visibility,
65         tt_volatility
66 } typetag_t;
67
68 typedef struct lex_entry
69 {
70         const char *str;
71         typetag_t   typetag;
72         unsigned    code;
73 } lex_entry;
74
75 typedef struct id_entry
76 {
77         long id;
78         void *elem;
79 } id_entry;
80
81 /** A set of lex_entry elements. */
82 static set *lexset;
83
84
85 static unsigned hash(const char *str, int len)
86 {
87         return str[0] * 27893 ^ str[len-1] * 81 ^ str[len >> 1];
88 }
89
90 static int lex_cmp(const void *elt, const void *key, size_t size)
91 {
92         const lex_entry *entry = (const lex_entry *) elt;
93         const lex_entry *keyentry = (const lex_entry *) key;
94         (void) size;
95         return strcmp(entry->str, keyentry->str);
96 }
97
98 static int id_cmp(const void *elt, const void *key, size_t size)
99 {
100         const id_entry *entry = (const id_entry *) elt;
101         const id_entry *keyentry = (const id_entry *) key;
102         (void) size;
103         return entry->id - keyentry->id;
104 }
105
106 /** Initializes the lexer. May be called more than once without problems. */
107 static void init_lexer(void)
108 {
109         lex_entry key;
110
111         /* Only initialize once */
112         if(lexset != NULL) return;
113
114         lexset = new_set(lex_cmp, 32);
115
116 #define INSERT(s, tt, cod)                                       \
117         key.str = (s);                                               \
118         key.typetag = (tt);                                          \
119         key.code = (cod);                                            \
120         set_insert(lexset, &key, sizeof(key), hash(s, sizeof(s)-1))
121
122 #define INSERTENUM(tt, e) INSERT(#e, tt, e)
123
124         INSERT("primitive", tt_tpo, tpo_primitive);
125         INSERT("method", tt_tpo, tpo_method);
126         INSERT("array", tt_tpo, tpo_array);
127         INSERT("struct", tt_tpo, tpo_struct);
128         INSERT("Unknown", tt_tpo, tpo_unknown);
129
130 #include "gen_irio_lex.inl"
131
132         INSERTENUM(tt_align, align_non_aligned);
133         INSERTENUM(tt_align, align_is_aligned);
134
135         INSERTENUM(tt_allocation, allocation_automatic);
136         INSERTENUM(tt_allocation, allocation_parameter);
137         INSERTENUM(tt_allocation, allocation_dynamic);
138         INSERTENUM(tt_allocation, allocation_static);
139
140         INSERTENUM(tt_pin_state, op_pin_state_floats);
141         INSERTENUM(tt_pin_state, op_pin_state_pinned);
142         INSERTENUM(tt_pin_state, op_pin_state_exc_pinned);
143         INSERTENUM(tt_pin_state, op_pin_state_mem_pinned);
144
145         INSERTENUM(tt_type_state, layout_undefined);
146         INSERTENUM(tt_type_state, layout_fixed);
147
148         INSERTENUM(tt_variability, variability_uninitialized);
149         INSERTENUM(tt_variability, variability_initialized);
150         INSERTENUM(tt_variability, variability_part_constant);
151         INSERTENUM(tt_variability, variability_constant);
152
153         INSERTENUM(tt_visibility, visibility_local);
154         INSERTENUM(tt_visibility, visibility_external_visible);
155         INSERTENUM(tt_visibility, visibility_external_allocated);
156
157         INSERTENUM(tt_volatility, volatility_non_volatile);
158         INSERTENUM(tt_volatility, volatility_is_volatile);
159
160         INSERTENUM(tt_peculiarity, peculiarity_description);
161         INSERTENUM(tt_peculiarity, peculiarity_inherited);
162         INSERTENUM(tt_peculiarity, peculiarity_existent);
163
164 #undef INSERTENUM
165 #undef INSERT
166 }
167
168 /** Returns the according enum entry for the given string and tag, or LEXERROR if none was found. */
169 static unsigned lex(const char *str, typetag_t typetag)
170 {
171         lex_entry key, *entry;
172
173         key.str = str;
174
175         entry = set_find(lexset, &key, sizeof(key), hash(str, strlen(str)));
176         if (entry && entry->typetag == typetag) {
177                 return entry->code;
178         }
179         return LEXERROR;
180 }
181
182 static void *get_id(io_env_t *env, long id)
183 {
184         id_entry key, *entry;
185         key.id = id;
186
187         entry = set_find(env->idset, &key, sizeof(key), (unsigned) id);
188         return entry ? entry->elem : NULL;
189 }
190
191 static void set_id(io_env_t *env, long id, void *elem)
192 {
193         id_entry key;
194         key.id = id;
195         key.elem = elem;
196         set_insert(env->idset, &key, sizeof(key), (unsigned) id);
197 }
198
199 static void write_mode(io_env_t *env, ir_mode *mode)
200 {
201         fputs(get_mode_name(mode), env->file);
202         fputc(' ', env->file);
203 }
204
205 static void write_pinned(io_env_t *env, ir_node *irn)
206 {
207         fputs(get_op_pin_state_name(get_irn_pinned(irn)), env->file);
208         fputc(' ', env->file);
209 }
210
211 static void write_volatility(io_env_t *env, ir_node *irn)
212 {
213         ir_volatility vol;
214
215         if(is_Load(irn)) vol = get_Load_volatility(irn);
216         else if(is_Store(irn)) vol = get_Store_volatility(irn);
217         else assert(0 && "Invalid optype for write_volatility");
218
219         fputs(get_volatility_name(vol), env->file);
220         fputc(' ', env->file);
221 }
222
223 static void write_align(io_env_t *env, ir_node *irn)
224 {
225         ir_align align;
226
227         if(is_Load(irn)) align = get_Load_align(irn);
228         else if(is_Store(irn)) align = get_Store_align(irn);
229         else assert(0 && "Invalid optype for write_align");
230
231         fputs(get_align_name(align), env->file);
232         fputc(' ', env->file);
233 }
234
235 static void export_type(io_env_t *env, ir_type *tp)
236 {
237         FILE *f = env->file;
238         int i;
239         fprintf(f, "\ttype %ld %s \"%s\" %u %u %s %s ",
240                         get_type_nr(tp),
241                         get_type_tpop_name(tp),
242                         get_type_name(tp),
243                         get_type_size_bytes(tp),
244                         get_type_alignment_bytes(tp),
245                         get_type_state_name(get_type_state(tp)),
246                         get_visibility_name(get_type_visibility(tp)));
247
248         switch(get_type_tpop_code(tp))
249         {
250                 case tpo_array:
251                 {
252                         int n = get_array_n_dimensions(tp);
253                         fprintf(f, "%i %ld ", n, get_type_nr(get_array_element_type(tp)));
254                         for(i = 0; i < n; i++)
255                         {
256                                 ir_node *lower = get_array_lower_bound(tp, i);
257                                 ir_node *upper = get_array_upper_bound(tp, i);
258
259                                 if(is_Const(lower)) fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(lower)));
260                                 else panic("Lower array bound is not constant");
261
262                                 if(is_Const(upper)) fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(upper)));
263                                 else panic("Upper array bound is not constant");
264                         }
265                         break;
266                 }
267
268                 case tpo_method:
269                 {
270                         int nparams = get_method_n_params(tp);
271                         int nresults = get_method_n_ress(tp);
272                         fprintf(f, "%i %i ", nparams, nresults);
273                         for(i = 0; i < nparams; i++)
274                                 fprintf(f, "%ld ", get_type_nr(get_method_param_type(tp, i)));
275                         for(i = 0; i < nresults; i++)
276                                 fprintf(f, "%ld ", get_type_nr(get_method_res_type(tp, i)));
277                         break;
278                 }
279
280                 case tpo_primitive:
281                 {
282                         write_mode(env, get_type_mode(tp));
283                         break;
284                 }
285
286                 case tpo_struct:
287                         break;
288
289                 case tpo_class:
290                         // TODO: inheritance stuff not supported yet
291                         printf("Inheritance of classes not supported yet!\n");
292                         break;
293
294                 case tpo_unknown:
295                         break;
296
297                 default:
298                         printf("export_type: Unknown type code \"%s\".\n", get_type_tpop_name(tp));
299                         break;
300         }
301         fputc('\n', f);
302 }
303
304 static void export_entity(io_env_t *env, ir_entity *ent)
305 {
306         ir_type *owner = get_entity_owner(ent);
307         fprintf(env->file, "\tentity %ld \"%s\" %ld %ld %d %d %s %s %s %s %s\n",
308                         get_entity_nr(ent),
309                         get_entity_name(ent),
310                         get_type_nr(get_entity_type(ent)),
311                         get_type_nr(owner),
312                         get_entity_offset(ent),
313                         (int) get_entity_offset_bits_remainder(ent),
314                         get_allocation_name(get_entity_allocation(ent)),
315                         get_visibility_name(get_entity_visibility(ent)),
316                         get_variability_name(get_entity_variability(ent)),
317                         get_peculiarity_name(get_entity_peculiarity(ent)),
318                         get_volatility_name(get_entity_volatility(ent)));
319
320         // TODO: inheritance stuff for class entities not supported yet
321         if(is_Class_type(owner) && owner != get_glob_type())
322                 printf("Inheritance of class entities not supported yet!\n");
323 }
324
325 static void export_type_or_ent(type_or_ent tore, void *ctx)
326 {
327         io_env_t *env = (io_env_t *) ctx;
328
329         switch(get_kind(tore.ent))
330         {
331                 case k_entity:
332                         export_entity(env, tore.ent);
333                         break;
334
335                 case k_type:
336                         export_type(env, tore.typ);
337                         break;
338
339                 default:
340                         printf("export_type_or_ent: Unknown type or entity.\n");
341                         break;
342         }
343 }
344
345 static void export_node(ir_node *irn, void *ctx)
346 {
347         io_env_t *env = (io_env_t *) ctx;
348         int i, n;
349         unsigned opcode = get_irn_opcode(irn);
350         char buf[1024];
351
352         if(env->ignoreblocks && opcode == iro_Block) return;
353
354         n = get_irn_arity(irn);
355
356         fprintf(env->file, "\n\t%s %ld [ ", get_irn_opname(irn), get_irn_node_nr(irn));
357
358         for(i = -1; i < n; i++)
359         {
360                 ir_node *pred = get_irn_n(irn, i);
361                 if(!pred)
362                         fputs("-1 ", env->file);
363                 else
364                         fprintf(env->file, "%ld ", get_irn_node_nr(pred));
365         }
366
367         fprintf(env->file, "] { ");
368
369         switch(opcode)
370         {
371                 #include "gen_irio_export.inl"
372         }
373         fputc('}', env->file);
374 }
375
376 /** Exports the given irg to the given file. */
377 void ir_export_irg(ir_graph *irg, const char *filename)
378 {
379         io_env_t env;
380
381         env.file = fopen(filename, "wt");
382         if(!env.file)
383         {
384                 perror(filename);
385                 return;
386         }
387
388         fputs("typegraph {\n", env.file);
389
390         type_walk_irg(irg, NULL, export_type_or_ent, &env);
391
392         fprintf(env.file, "}\n\nirg %ld {", get_entity_nr(get_irg_entity(irg)));
393
394         env.ignoreblocks = 0;
395         irg_block_walk_graph(irg, NULL, export_node, &env);
396
397         env.ignoreblocks = 1;
398         irg_walk_anchors(irg, NULL, export_node, &env);
399
400         fputs("\n}\n", env.file);
401
402         fclose(env.file);
403 }
404
405 static int read_c(io_env_t *env)
406 {
407         int ch = fgetc(env->file);
408         switch(ch)
409         {
410                 case '\t':
411                         env->col += 4;
412                         break;
413
414                 case '\n':
415                         env->col = 0;
416                         env->line++;
417                         break;
418
419                 default:
420                         env->col++;
421                         break;
422         }
423         return ch;
424 }
425
426 /** Returns the first non-whitespace character or EOF. **/
427 static int skip_ws(io_env_t *env)
428 {
429         while(1)
430         {
431                 int ch = read_c(env);
432                 switch(ch)
433                 {
434                         case ' ':
435                         case '\t':
436                         case '\n':
437                         case '\r':
438                                 break;
439
440                         default:
441                                 return ch;
442                 }
443         }
444 }
445
446 static void skip_to(io_env_t *env, char to_ch)
447 {
448         int ch;
449         do
450         {
451                 ch = read_c(env);
452         }
453         while(ch != to_ch && ch != EOF);
454 }
455
456 static int expect_char(io_env_t *env, char ch)
457 {
458         int curch = skip_ws(env);
459         if(curch != ch)
460         {
461                 printf("Unexpected char '%c', expected '%c' in line %i:%i\n", curch, ch, env->line, env->col);
462                 return 0;
463         }
464         return 1;
465 }
466
467 #define EXPECT(c) if(expect_char(env, (c))) {} else return 0
468 #define EXPECT_OR_EXIT(c) if(expect_char(env, (c))) {} else exit(1)
469
470 inline static const char *read_str_to(io_env_t *env, char *buf, size_t bufsize)
471 {
472         size_t i;
473         for(i = 0; i < bufsize - 1; i++)
474         {
475                 int ch = read_c(env);
476                 if(ch == EOF) break;
477                 switch(ch)
478                 {
479                         case ' ':
480                         case '\t':
481                         case '\n':
482                         case '\r':
483                                 if(i != 0)
484                                         goto endofword;
485                                 i--;    // skip whitespace
486                                 break;
487
488                         default:
489                                 buf[i] = ch;
490                                 break;
491                 }
492         }
493 endofword:
494         buf[i] = 0;
495         return buf;
496 }
497
498 static const char *read_str(io_env_t *env)
499 {
500         static char buf[1024];
501         return read_str_to(env, buf, sizeof(buf));
502 }
503
504 static const char *read_qstr_to(io_env_t *env, char *buf, size_t bufsize)
505 {
506         size_t i;
507         EXPECT_OR_EXIT('\"');
508         for(i = 0; i < bufsize - 1; i++)
509         {
510                 int ch = read_c(env);
511                 if(ch == EOF)
512                 {
513                         printf("Unexpected end of quoted string!\n");
514                         exit(1);
515                 }
516                 if(ch == '\"') break;
517
518                 buf[i] = ch;
519         }
520         if(i == bufsize - 1)
521         {
522                 printf("Quoted string too long!\n");
523                 exit(1);
524         }
525         buf[i] = 0;
526         return buf;
527 }
528
529 static long read_long2(io_env_t *env, char **endptr)
530 {
531         static char buf[1024];
532         return strtol(read_str_to(env, buf, sizeof(buf)), endptr, 0);
533 }
534
535 static long read_long(io_env_t *env)
536 {
537         return read_long2(env, NULL);
538 }
539
540 static ir_node *get_node_or_null(io_env_t *env, long nodenr)
541 {
542         ir_node *node = (ir_node *) get_id(env, nodenr);
543         if(node && node->kind != k_ir_node)
544         {
545                 panic("Irn ID %ld collides with something else in line %i:%i\n", nodenr, env->line, env->col);
546         }
547         return node;
548 }
549
550 static ir_node *get_node(io_env_t *env, long nodenr)
551 {
552         ir_node *node = get_node_or_null(env, nodenr);
553         if(!node)
554                 panic("Unknown node: %ld in line %i:%i\n", nodenr, env->line, env->col);
555
556         return node;
557 }
558
559 static ir_node *get_node_or_dummy(io_env_t *env, long nodenr)
560 {
561         ir_node *node = get_node_or_null(env, nodenr);
562         if(!node)
563         {
564                 node = new_Dummy(mode_X);
565                 set_id(env, nodenr, node);
566         }
567         return node;
568 }
569
570 static ir_type *get_type(io_env_t *env, long typenr)
571 {
572         ir_type *type = (ir_type *) get_id(env, typenr);
573         if(!type)
574         {
575                 panic("Unknown type: %ld in line %i:%i\n", typenr, env->line, env->col);
576         }
577         else if(type->kind != k_type)
578         {
579                 panic("Type ID %ld collides with something else in line %i:%i\n", typenr, env->line, env->col);
580         }
581         return type;
582 }
583
584 static ir_type *read_type(io_env_t *env)
585 {
586         return get_type(env, read_long(env));
587 }
588
589 static ir_entity *get_entity(io_env_t *env, long entnr)
590 {
591         ir_entity *entity = (ir_entity *) get_id(env, entnr);
592         if(!entity)
593         {
594                 printf("Unknown entity: %ld in line %i:%i\n", entnr, env->line, env->col);
595                 exit(1);
596         }
597         else if(entity->kind != k_entity)
598         {
599                 panic("Entity ID %ld collides with something else in line %i:%i\n", entnr, env->line, env->col);
600         }
601         return entity;
602 }
603
604 static ir_entity *read_entity(io_env_t *env)
605 {
606         return get_entity(env, read_long(env));
607 }
608
609 static ir_mode *read_mode(io_env_t *env)
610 {
611         static char buf[128];
612         int i, n;
613
614         read_str_to(env, buf, sizeof(buf));
615
616         n = get_irp_n_modes();
617         for(i = 0; i < n; i++)
618         {
619                 ir_mode *mode = get_irp_mode(i);
620                 if(!strcmp(buf, get_mode_name(mode)))
621                         return mode;
622         }
623
624         printf("Unknown mode \"%s\" in line %i:%i\n", buf, env->line, env->col);
625         return mode_ANY;
626 }
627
628 static const char *get_typetag_name(typetag_t typetag)
629 {
630         switch(typetag)
631         {
632                 case tt_iro:         return "opcode";
633                 case tt_tpo:         return "type";
634                 case tt_align:       return "align";
635                 case tt_allocation:  return "allocation";
636                 case tt_peculiarity: return "peculiarity";
637                 case tt_pin_state:   return "pin state";
638                 case tt_type_state:  return "type state";
639                 case tt_variability: return "variability";
640                 case tt_visibility:  return "visibility";
641                 case tt_volatility:  return "volatility";
642                 default: return "<UNKNOWN>";
643         }
644 }
645
646 static unsigned read_enum(io_env_t *env, typetag_t typetag)
647 {
648         static char buf[128];
649         unsigned code = lex(read_str_to(env, buf, sizeof(buf)), typetag);
650         if(code != LEXERROR) return code;
651
652         printf("Invalid %s: \"%s\" in %i:%i\n", get_typetag_name(typetag), buf, env->line, env->col);
653         return 0;
654 }
655
656 #define read_align(env)       ((ir_align)       read_enum(env, tt_align))
657 #define read_allocation(env)  ((ir_allocation)  read_enum(env, tt_allocation))
658 #define read_peculiarity(env) ((ir_peculiarity) read_enum(env, tt_peculiarity))
659 #define read_pinned(env)      ((op_pin_state)   read_enum(env, tt_pin_state))
660 #define read_type_state(env)  ((ir_type_state)  read_enum(env, tt_type_state))
661 #define read_variability(env) ((ir_variability) read_enum(env, tt_variability))
662 #define read_visibility(env)  ((ir_visibility)  read_enum(env, tt_visibility))
663 #define read_volatility(env)  ((ir_volatility)  read_enum(env, tt_volatility))
664
665 static tarval *read_tv(io_env_t *env)
666 {
667         static char buf[128];
668         ir_mode *tvmode = read_mode(env);
669         read_str_to(env, buf, sizeof(buf));
670         return new_tarval_from_str(buf, strlen(buf), tvmode);
671 }
672
673 /** Reads a type description and remembers it by its id. */
674 static void import_type(io_env_t *env)
675 {
676         char           buf[1024];
677         int            i;
678         ir_type       *type;
679         long           typenr = read_long(env);
680         const char    *tpop   = read_str(env);
681         const char    *name   = read_qstr_to(env, buf, sizeof(buf));
682         unsigned       size   = (unsigned) read_long(env);
683         unsigned       align  = (unsigned) read_long(env);
684         ir_type_state  state  = read_type_state(env);
685         ir_visibility  vis    = read_visibility(env);
686
687         ident         *id     = new_id_from_str(name);
688
689         switch(lex(tpop, tt_tpo))
690         {
691                 case tpo_primitive:
692                 {
693                         ir_mode *mode = read_mode(env);
694                         type = new_type_primitive(id, mode);
695                         break;
696                 }
697
698                 case tpo_method:
699                 {
700                         int nparams  = (int) read_long(env);
701                         int nresults = (int) read_long(env);
702
703                         type = new_type_method(id, nparams, nresults);
704
705                         for(i = 0; i < nparams; i++)
706                         {
707                                 long     typenr = read_long(env);
708                                 ir_type *paramtype = get_type(env, typenr);
709
710                                 set_method_param_type(type, i, paramtype);
711                         }
712                         for(i = 0; i < nresults; i++)
713                         {
714                                 long typenr = read_long(env);
715                                 ir_type *restype = get_type(env, typenr);
716
717                                 set_method_res_type(type, i, restype);
718                         }
719                         break;
720                 }
721
722                 case tpo_array:
723                 {
724                         int ndims = (int) read_long(env);
725                         long elemtypenr = read_long(env);
726                         ir_type *elemtype = get_type(env, elemtypenr);
727
728                         type = new_type_array(id, ndims, elemtype);
729                         for(i = 0; i < ndims; i++)
730                         {
731                                 long lowerbound = read_long(env);
732                                 long upperbound = read_long(env);
733                                 set_array_bounds_int(type, i, lowerbound, upperbound);
734                         }
735                         set_type_size_bytes(type, size);
736                         break;
737                 }
738
739                 case tpo_class:
740                         type = new_type_class(id);
741                         set_type_size_bytes(type, size);
742                         break;
743
744                 case tpo_struct:
745                         type = new_type_struct(id);
746                         set_type_size_bytes(type, size);
747                         break;
748
749                 case tpo_union:
750                         type = new_type_union(id);
751                         set_type_size_bytes(type, size);
752                         break;
753
754                 case tpo_unknown:
755                         return;   // ignore unknown type
756
757                 default:
758                         if(typenr != 0)  // ignore global type
759                                 printf("Unknown type kind: \"%s\" in line %i:%i\n", tpop, env->line, env->col);
760                         skip_to(env, '\n');
761                         return;
762         }
763
764         set_type_alignment_bytes(type, align);
765         set_type_visibility(type, vis);
766
767         if(state == layout_fixed)
768                 ARR_APP1(ir_type *, env->fixedtypes, type);
769
770         set_id(env, typenr, type);
771         printf("Insert type %s %ld\n", name, typenr);
772 }
773
774 /** Reads an entity description and remembers it by its id. */
775 static void import_entity(io_env_t *env)
776 {
777         char          buf[1024];
778         long          entnr       = read_long(env);
779         const char   *name        = read_qstr_to(env, buf, sizeof(buf));
780         long          typenr      = read_long(env);
781         long          ownertypenr = read_long(env);
782
783         ir_type   *type      = get_type(env, typenr);
784         ir_type   *ownertype = !ownertypenr ? get_glob_type() : get_type(env, ownertypenr);
785         ir_entity *entity    = new_entity(ownertype, new_id_from_str(name), type);
786
787         set_entity_offset     (entity, (int) read_long(env));
788         set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
789         set_entity_allocation (entity, read_allocation(env));
790         set_entity_visibility (entity, read_visibility(env));
791         set_entity_variability(entity, read_variability(env));
792         set_entity_peculiarity(entity, read_peculiarity(env));
793         set_entity_volatility (entity, read_volatility(env));
794
795         set_id(env, entnr, entity);
796         printf("Insert entity %s %ld\n", name, entnr);
797 }
798
799 /** Parses the whole type graph. */
800 static int parse_typegraph(io_env_t *env)
801 {
802         const char *kind;
803         long curfpos;
804
805         EXPECT('{');
806
807         curfpos = ftell(env->file);
808
809         // parse all types first
810         while(1)
811         {
812                 kind = read_str(env);
813                 if(kind[0] == '}' && !kind[1]) break;
814
815                 if(!strcmp(kind, "type"))
816                         import_type(env);
817                 else
818                         skip_to(env, '\n');
819         }
820
821         // now parse rest
822         fseek(env->file, curfpos, SEEK_SET);
823         while(1)
824         {
825                 kind = read_str(env);
826                 if(kind[0] == '}' && !kind[1]) break;
827
828                 if(!strcmp(kind, "type"))
829                         skip_to(env, '\n');
830                 else if(!strcmp(kind, "entity"))
831                         import_entity(env);
832                 else
833                 {
834                         printf("Type graph element not supported yet: \"%s\"\n", kind);
835                         skip_to(env, '\n');
836                 }
837         }
838         return 1;
839 }
840
841 static int read_node_header(io_env_t *env, long *nodenr, long **preds, const char **nodename)
842 {
843         int numpreds;
844         *nodename = read_str(env);
845         if((*nodename)[0] == '}' && !(*nodename)[1]) return -1;  // end-of-graph
846
847         *nodenr = read_long(env);
848
849         ARR_RESIZE(ir_node *, *preds, 0);
850
851         EXPECT('[');
852         for(numpreds = 0; !feof(env->file); numpreds++)
853         {
854                 char *endptr;
855                 ARR_APP1(long, *preds, read_long2(env, &endptr));
856                 if(*endptr == ']') break;
857         }
858         return numpreds;
859 }
860
861 /** Parses an IRG. */
862 static int parse_graph(io_env_t *env)
863 {
864         long       *preds = NEW_ARR_F(long, 16);
865         ir_node   **prednodes = NEW_ARR_F(ir_node *, 16);
866         int         i, numpreds, ret = 1;
867         long        nodenr;
868         const char *nodename;
869         ir_node    *node, *newnode;
870
871         current_ir_graph = new_ir_graph(get_entity(env, read_long(env)), 0);
872
873         EXPECT('{');
874
875         while(1)
876         {
877                 numpreds = read_node_header(env, &nodenr, &preds, &nodename);
878                 if(numpreds == -1) break;  // end-of-graph
879                 if(!numpreds)
880                 {
881                         printf("Node %s %ld is missing predecessors!", nodename, nodenr);
882                         ret = 0;
883                         break;
884                 }
885
886                 ARR_RESIZE(ir_node *, prednodes, numpreds);
887                 for(i = 0; i < numpreds - 1; i++)
888                         prednodes[i] = get_node_or_dummy(env, preds[i + 1]);
889
890                 node = get_node_or_null(env, nodenr);
891                 newnode = NULL;
892
893                 EXPECT('{');
894
895                 switch(lex(nodename, tt_iro))
896                 {
897                         case iro_End:
898                         {
899                                 ir_node *newendblock = get_node(env, preds[0]);
900                                 newnode = get_irg_end(current_ir_graph);
901                                 exchange(get_nodes_block(newnode), newendblock);
902                                 break;
903                         }
904
905                         case iro_Start:
906                         {
907                                 ir_node *newstartblock = get_node(env, preds[0]);
908                                 newnode = get_irg_start(current_ir_graph);
909                                 exchange(get_nodes_block(newnode), newstartblock);
910                                 break;
911                         }
912
913                         case iro_Block:
914                         {
915                                 if(preds[0] != nodenr)
916                                 {
917                                         printf("Invalid block: preds[0] != nodenr (%ld != %ld)\n",
918                                                 preds[0], nodenr);
919                                         ret = 0;
920                                         goto endloop;
921                                 }
922
923                                 newnode = new_Block(numpreds - 1, prednodes);
924                                 break;
925                         }
926
927                         case iro_Anchor:
928                                 newnode = current_ir_graph->anchor;
929                                 for(i = 0; i < numpreds - 1; i++)
930                                         set_irn_n(newnode, i, prednodes[i]);
931                                 set_irn_n(newnode, -1, get_node(env, preds[0]));
932                                 break;
933
934                         case iro_SymConst:
935                         {
936                                 long entnr = read_long(env);
937                                 union symconst_symbol sym;
938                                 sym.entity_p = get_entity(env, entnr);
939                                 newnode = new_SymConst(mode_P, sym, symconst_addr_ent);
940                                 break;
941                         }
942
943                         #include "gen_irio_import.inl"
944
945                         default:
946                                 goto notsupported;
947                 }
948
949                 EXPECT('}');
950
951                 if(!newnode)
952                 {
953 notsupported:
954                         printf("Node type not supported yet: %s in line %i:%i\n", nodename, env->line, env->col);
955                         assert(0 && "Invalid node type");
956                 }
957
958                 if(node)
959                         exchange(node, newnode);
960                 /* Always update hash entry to avoid more uses of id nodes */
961                 set_id(env, nodenr, newnode);
962                 printf("Insert %s %ld\n", nodename, nodenr);
963         }
964
965 endloop:
966         DEL_ARR_F(preds);
967         DEL_ARR_F(prednodes);
968
969         return ret;
970 }
971
972 /** Imports an previously exported textual representation of an (maybe partial) irp */
973 void ir_import(const char *filename)
974 {
975         int oldoptimize = get_optimize();
976         firm_verification_t oldver = get_node_verification_mode();
977         io_env_t ioenv;
978         io_env_t *env = &ioenv;
979         int i, n;
980
981         init_lexer();
982
983         memset(env, 0, sizeof(*env));
984         env->idset = new_set(id_cmp, 128);
985         env->fixedtypes = NEW_ARR_F(ir_type *, 0);
986
987         env->file = fopen(filename, "rt");
988         if(!env->file)
989         {
990                 perror(filename);
991                 exit(1);
992         }
993
994         set_optimize(0);
995         do_node_verification(FIRM_VERIFICATION_OFF);
996
997         while(1)
998         {
999                 const char *str = read_str(env);
1000                 if(!*str) break;
1001                 if(!strcmp(str, "typegraph"))
1002                 {
1003                         if(!parse_typegraph(env)) break;
1004                 }
1005                 else if(!strcmp(str, "irg"))
1006                 {
1007                         if(!parse_graph(env)) break;
1008                 }
1009         }
1010
1011         n = ARR_LEN(env->fixedtypes);
1012         for(i = 0; i < n; i++)
1013                 set_type_state(env->fixedtypes[i], layout_fixed);
1014
1015         DEL_ARR_F(env->fixedtypes);
1016
1017         del_set(env->idset);
1018
1019         irp_finalize_cons();
1020
1021         do_node_verification(oldver);
1022         set_optimize(oldoptimize);
1023
1024         fclose(env->file);
1025 }