irio: complete rewrite
authorMatthias Braun <matze@braunis.de>
Wed, 16 Nov 2011 18:53:52 +0000 (19:53 +0100)
committerMatthias Braun <matze@braunis.de>
Thu, 17 Nov 2011 16:32:36 +0000 (17:32 +0100)
This should fix all known bugs, make the code easier to read and more
robust.

include/libfirm/irio.h
include/libfirm/irmode.h
ir/ir/irio.c
ir/ir/irmode.c
scripts/gen_ir_io.py
scripts/ir_spec.py

index 0a9e2c6..a188072 100644 (file)
 
 /**
  * Exports the whole irp to the given file in a textual form.
+ * Exports all types, all ir graphs, and the constant graph.
  *
  * @param filename  the name of the resulting file
- *
- * Exports all types, all ir graphs, and the constant graph.
+ * @return  0 if no errors occured, other values in case of errors
  */
-FIRM_API void ir_export(const char *filename);
+FIRM_API int ir_export(const char *filename);
 
 /**
  * same as ir_export but writes to a FILE*
+ * @note As with any FILE* errors are indicated by ferror(output)
  */
-FIRM_API void ir_export_file(FILE *output, const char *outputname);
-
-/**
- * Write the given ir graph to a stream in a textual format
- *
- * @param irg         the ir graph
- * @param output      output stream the irg is written to
- * @param outputname  a name for the output stream (used for error messages)
- *
- * Exports the type graph used by the given graph and the graph itself.
- */
-FIRM_API void ir_export_irg(ir_graph *irg, FILE *output,
-                            const char *outputname);
+FIRM_API void ir_export_file(FILE *output);
 
 /**
  * Imports the data stored in the given file.
+ * Imports any type graphs and ir graphs contained in the file.
  *
  * @param filename  the name of the file
- *
- * Imports any type graphs and ir graphs contained in the file.
+ * @returns 0 if no errors occured, other values in case of errors
  */
-FIRM_API void ir_import(const char *filename);
+FIRM_API int ir_import(const char *filename);
 
 /**
  * same as ir_import but imports from a FILE*
  */
-FIRM_API void ir_import_file(FILE *input, const char *inputname);
+FIRM_API int ir_import_file(FILE *input, const char *inputname);
 
 #include "end.h"
 
index 404c67a..cb26aca 100644 (file)
@@ -53,12 +53,9 @@ typedef enum ir_mode_arithmetic {
                                       to ieee754 floating point standard.  Only
                                       legal for modes of sort float_number. */
        irma_x86_extended_float,  /**< x86 extended floatingpoint values */
-       irma_max
+       irma_last = irma_x86_extended_float,
 } ir_mode_arithmetic;
 
-/** Returns the name of the arithmetic type. */
-FIRM_API const char *get_mode_arithmetic_name(ir_mode_arithmetic ari);
-
 /**
  * Creates a new mode.
  *
index e897533..387bac6 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @file
  * @brief   Write textual representation of firm to file.
- * @author  Moritz Kroll
+ * @author  Moritz Kroll, Matthias Braun
  */
 #include "config.h"
 
@@ -35,7 +35,7 @@
 #include "irprog.h"
 #include "irgraph_t.h"
 #include "irprintf.h"
-#include "ircons.h"
+#include "ircons_t.h"
 #include "irgmod.h"
 #include "irflag_t.h"
 #include "irgwalk.h"
 #include "array.h"
 #include "error.h"
 #include "typerep.h"
-#include "adt/set.h"
-#include "adt/obst.h"
+#include "set.h"
+#include "obst.h"
+#include "pmap.h"
+#include "pdeq.h"
 
 #define SYMERROR ((unsigned) ~0)
 
-typedef struct io_env_t
-{
-       int c;                /**< currently read char */
-       FILE *file;
-       set *idset;           /**< id_entry set, which maps from file ids to new Firm elements */
-       int ignoreblocks;
-       const char *inputname;
-       int line;
-       ir_type **fixedtypes;
+static void register_generated_node_readers(void);
+static void register_generated_node_writers(void);
+
+typedef struct delayed_initializer_t {
+       ir_initializer_t *initializer;
+       long              node_nr;
+} delayed_initializer_t;
+
+typedef struct delayed_pred_t {
+       ir_node *node;
+       int      n_preds;
+       long     preds[];
+} delayed_pred_t;
+
+typedef struct read_env_t {
+       int            c;           /**< currently read char */
+       FILE          *file;
+       const char    *inputname;
+       unsigned       line;
+
+       ir_graph      *irg;
+       set           *idset;       /**< id_entry set, which maps from file ids to
+                                        new Firm elements */
+       ir_type      **fixedtypes;
+       bool           read_errors;
        struct obstack obst;
-       ir_graph *irg;
-} io_env_t;
+       struct obstack preds_obst;
+       delayed_initializer_t *delayed_initializers;
+       const delayed_pred_t **delayed_preds;
+} read_env_t;
 
-typedef enum typetag_t
-{
+typedef struct write_env_t {
+       FILE *file;
+       pdeq *write_queue;
+} write_env_t;
+
+typedef enum typetag_t {
        tt_align,
-       tt_allocation,
-       tt_builtin,
+       tt_builtin_kind,
        tt_cond_jmp_predicate,
        tt_initializer,
-       tt_iro,
+       tt_irg_inline_property,
        tt_keyword,
+       tt_linkage,
        tt_mode_arithmetic,
        tt_pin_state,
+       tt_segment,
+       tt_throws,
        tt_tpo,
        tt_type_state,
+       tt_visibility,
        tt_volatility,
-       tt_linkage,
-       tt_segment,
-       tt_visibility
+       tt_where_alloc,
 } typetag_t;
 
-typedef enum keyword_t
-{
+typedef enum keyword_t {
+       kw_asm,
+       kw_compound_member,
        kw_constirg,
        kw_entity,
-       kw_irg,
-       kw_int_mode,
-       kw_reference_mode,
        kw_float_mode,
+       kw_int_mode,
+       kw_irg,
+       kw_label,
+       kw_method,
        kw_modes,
+       kw_parameter,
+       kw_program,
+       kw_reference_mode,
+       kw_segment_type,
        kw_type,
        kw_typegraph,
-       kw_program,
-       kw_segment_type
 } keyword_t;
 
-typedef struct symbol_t
-{
+typedef struct symbol_t {
        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;
 
-typedef struct id_entry
-{
+typedef struct id_entry {
        long id;
        void *elem;
 } id_entry;
@@ -134,10 +161,10 @@ static int id_cmp(const void *elt, const void *key, size_t size)
 }
 
 static void __attribute__((format(printf, 2, 3)))
-parse_error(io_env_t *env, const char *fmt, ...)
+parse_error(read_env_t *env, const char *fmt, ...)
 {
-       va_list ap;
-       int     line = env->line;
+       va_list  ap;
+       unsigned line = env->line;
 
        /* workaround read_c "feature" that a '\n' triggers the line++
         * instead of the character after the '\n' */
@@ -145,7 +172,11 @@ parse_error(io_env_t *env, const char *fmt, ...)
                line--;
        }
 
-       fprintf(stderr, "%s:%d: error ", env->inputname, line);
+       fprintf(stderr, "%s:%u: error ", env->inputname, line);
+       env->read_errors = true;
+
+       /* let's hope firm doesn't die on further errors */
+       do_node_verification(0);
 
        va_start(ap, fmt);
        vfprintf(stderr, fmt, ap);
@@ -197,37 +228,43 @@ static void symtbl_init(void)
        INSERT(tt_visibility, "default", ir_visibility_default);
        INSERT(tt_visibility, "private", ir_visibility_private);
 
+       INSERT(tt_throws, "throw",   true);
+       INSERT(tt_throws, "nothrow", false);
+
+       INSERTKEYWORD(asm);
+       INSERTKEYWORD(compound_member);
        INSERTKEYWORD(constirg);
        INSERTKEYWORD(entity);
-       INSERTKEYWORD(irg);
-       INSERTKEYWORD(int_mode);
        INSERTKEYWORD(float_mode);
-       INSERTKEYWORD(reference_mode);
+       INSERTKEYWORD(int_mode);
+       INSERTKEYWORD(irg);
+       INSERTKEYWORD(label);
+       INSERTKEYWORD(method);
        INSERTKEYWORD(modes);
-       INSERTKEYWORD(type);
-       INSERTKEYWORD(typegraph);
+       INSERTKEYWORD(parameter);
        INSERTKEYWORD(program);
+       INSERTKEYWORD(reference_mode);
        INSERTKEYWORD(segment_type);
-
-#include "gen_irio_lex.inl"
+       INSERTKEYWORD(type);
+       INSERTKEYWORD(typegraph);
 
        INSERTENUM(tt_align, align_non_aligned);
        INSERTENUM(tt_align, align_is_aligned);
 
-       INSERTENUM(tt_builtin, ir_bk_trap);
-       INSERTENUM(tt_builtin, ir_bk_debugbreak);
-       INSERTENUM(tt_builtin, ir_bk_return_address);
-       INSERTENUM(tt_builtin, ir_bk_frame_address);
-       INSERTENUM(tt_builtin, ir_bk_prefetch);
-       INSERTENUM(tt_builtin, ir_bk_ffs);
-       INSERTENUM(tt_builtin, ir_bk_clz);
-       INSERTENUM(tt_builtin, ir_bk_ctz);
-       INSERTENUM(tt_builtin, ir_bk_popcount);
-       INSERTENUM(tt_builtin, ir_bk_parity);
-       INSERTENUM(tt_builtin, ir_bk_bswap);
-       INSERTENUM(tt_builtin, ir_bk_inport);
-       INSERTENUM(tt_builtin, ir_bk_outport);
-       INSERTENUM(tt_builtin, ir_bk_inner_trampoline);
+       INSERTENUM(tt_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);
+       INSERTENUM(tt_builtin_kind, ir_bk_inner_trampoline);
 
        INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_NONE);
        INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_TRUE);
@@ -238,10 +275,17 @@ static void symtbl_init(void)
        INSERTENUM(tt_initializer, IR_INITIALIZER_NULL);
        INSERTENUM(tt_initializer, IR_INITIALIZER_COMPOUND);
 
-       INSERTENUM(tt_mode_arithmetic, irma_uninitialized);
-       INSERTENUM(tt_mode_arithmetic, irma_none);
-       INSERTENUM(tt_mode_arithmetic, irma_twos_complement);
-       INSERTENUM(tt_mode_arithmetic, irma_ieee754);
+       INSERT(tt_mode_arithmetic, "uninitialized",      irma_uninitialized);
+       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);
+
+       INSERT(tt_irg_inline_property, "any",            irg_inline_any);
+       INSERT(tt_irg_inline_property, "recommended",    irg_inline_recomended);
+       INSERT(tt_irg_inline_property, "forbidden",      irg_inline_forbidden);
+       INSERT(tt_irg_inline_property, "forced",         irg_inline_forced);
+       INSERT(tt_irg_inline_property, "forced_no_body", irg_inline_forced_no_body);
 
        INSERTENUM(tt_pin_state, op_pin_state_floats);
        INSERTENUM(tt_pin_state, op_pin_state_pinned);
@@ -254,6 +298,9 @@ static void symtbl_init(void)
        INSERTENUM(tt_volatility, volatility_non_volatile);
        INSERTENUM(tt_volatility, volatility_is_volatile);
 
+       INSERTENUM(tt_where_alloc, stack_alloc);
+       INSERTENUM(tt_where_alloc, heap_alloc);
+
 #undef INSERTKEYWORD
 #undef INSERTENUM
 #undef INSERT
@@ -267,7 +314,7 @@ static const char *get_segment_name(ir_segment_t segment)
        case IR_SEGMENT_CONSTRUCTORS: return "constructors";
        case IR_SEGMENT_DESTRUCTORS:  return "destructors";
        }
-       return "INVALID_SEGMENT";
+       panic("INVALID_SEGMENT");
 }
 
 static const char *get_visibility_name(ir_visibility visibility)
@@ -278,7 +325,31 @@ static const char *get_visibility_name(ir_visibility visibility)
        case ir_visibility_default:  return "default";
        case ir_visibility_private:  return "private";
        }
-       return "INVALID_VISIBILITY";
+       panic("INVALID_VISIBILITY");
+}
+
+static const char *get_mode_arithmetic_name(ir_mode_arithmetic arithmetic)
+{
+       switch (arithmetic) {
+       case irma_uninitialized:      return "uninitialized";
+       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");
+}
+
+static const char *get_irg_inline_property_name(irg_inline_property prop)
+{
+       switch (prop) {
+       case irg_inline_any:            return "any";
+       case irg_inline_recomended:     return "recommended";
+       case irg_inline_forbidden:      return "forbidden";
+       case irg_inline_forced:         return "forced";
+       case irg_inline_forced_no_body: return "forced_no_body";
+       }
+       panic("invalid irg_inline_property");
 }
 
 /** Returns the according symbol value for the given string and tag, or SYMERROR if none was found. */
@@ -293,49 +364,51 @@ static unsigned symbol(const char *str, typetag_t typetag)
        return entry ? entry->code : SYMERROR;
 }
 
-static void *get_id(io_env_t *env, long id)
+static void write_long(write_env_t *env, long value)
 {
-       id_entry key, *entry;
-       key.id = id;
-
-       entry = (id_entry*)set_find(env->idset, &key, sizeof(key), (unsigned) id);
-       return entry ? entry->elem : NULL;
+       fprintf(env->file, "%ld ", value);
 }
 
-static void set_id(io_env_t *env, long id, void *elem)
+static void write_int(write_env_t *env, int value)
 {
-       id_entry key;
-       key.id = id;
-       key.elem = elem;
-       set_insert(env->idset, &key, sizeof(key), (unsigned) id);
+       fprintf(env->file, "%d ", value);
 }
 
-static void write_long(io_env_t *env, long value)
+static void write_unsigned(write_env_t *env, unsigned value)
 {
-       fprintf(env->file, "%ld ", value);
+       fprintf(env->file, "%u ", value);
 }
 
-static void write_int(io_env_t *env, int value)
+static void write_size_t(write_env_t *env, size_t value)
 {
-       fprintf(env->file, "%d ", value);
+       ir_fprintf(env->file, "%zu ", value);
 }
 
-static void write_unsigned(io_env_t *env, unsigned value)
+static void write_symbol(write_env_t *env, const char *symbol)
 {
-       fprintf(env->file, "%u ", value);
+       fputs(symbol, env->file);
+       fputc(' ', env->file);
 }
 
-static void write_entity_ref(io_env_t *env, ir_entity *entity)
+static void write_entity_ref(write_env_t *env, ir_entity *entity)
 {
        write_long(env, get_entity_nr(entity));
 }
 
-static void write_type_ref(io_env_t *env, ir_type *type)
+static void write_type_ref(write_env_t *env, ir_type *type)
 {
-       write_long(env, get_type_nr(type));
+       if (type == firm_unknown_type) {
+               write_symbol(env, "unknown");
+       } else if (type == firm_none_type) {
+               write_symbol(env, "none");
+       } else if (type == firm_code_type) {
+               write_symbol(env, "code");
+       } else {
+               write_long(env, get_type_nr(type));
+       }
 }
 
-static void write_string(io_env_t *env, const char *string)
+static void write_string(write_env_t *env, const char *string)
 {
        const char *c;
        fputc('"', env->file);
@@ -355,15 +428,15 @@ static void write_string(io_env_t *env, const char *string)
                }
        }
        fputc('"', env->file);
+       fputc(' ', env->file);
 }
 
-static void write_ident(io_env_t *env, ident *id)
+static void write_ident(write_env_t *env, ident *id)
 {
        write_string(env, get_id_str(id));
-       fputc(' ', env->file);
 }
 
-static void write_ident_null(io_env_t *env, ident *id)
+static void write_ident_null(write_env_t *env, ident *id)
 {
        if (id == NULL) {
                fputs("NULL ", env->file);
@@ -372,50 +445,87 @@ static void write_ident_null(io_env_t *env, ident *id)
        }
 }
 
-static void write_mode(io_env_t *env, ir_mode *mode)
+static void write_mode_ref(write_env_t *env, ir_mode *mode)
 {
        write_string(env, get_mode_name(mode));
-       fputc(' ', env->file);
 }
 
-static void write_tarval(io_env_t *env, ir_tarval *tv)
+static void write_tarval(write_env_t *env, ir_tarval *tv)
 {
-       char buf[1024];
-       write_mode(env, get_tarval_mode(tv));
-       tarval_snprintf(buf, sizeof(buf), tv);
-       fputs(buf, env->file);
-       fputc(' ', env->file);
+       write_mode_ref(env, get_tarval_mode(tv));
+       if (tv == tarval_bad) {
+               write_symbol(env, "bad");
+       } else {
+               char buf[1024];
+               tarval_snprintf(buf, sizeof(buf), tv);
+               fputs(buf, env->file);
+               fputc(' ', env->file);
+       }
 }
 
-static void write_align(io_env_t *env, ir_align align)
+static void write_align(write_env_t *env, ir_align align)
 {
        fputs(get_align_name(align), env->file);
        fputc(' ', env->file);
 }
 
-static void write_builtin_kind(io_env_t *env, ir_node *irn)
+static void write_builtin_kind(write_env_t *env, const ir_node *node)
 {
-       fputs(get_builtin_kind_name(get_Builtin_kind(irn)), env->file);
+       fputs(get_builtin_kind_name(get_Builtin_kind(node)), env->file);
        fputc(' ', env->file);
 }
 
-static void write_cond_jmp_predicate(io_env_t *env, ir_node *irn)
+static void write_cond_jmp_predicate(write_env_t *env, const ir_node *node)
 {
-       fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(irn)), env->file);
+       fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(node)), env->file);
        fputc(' ', env->file);
 }
 
-static void write_list_begin(io_env_t *env)
+static void write_relation(write_env_t *env, ir_relation relation)
+{
+       write_long(env, (long)relation);
+}
+
+static void write_where_alloc(write_env_t *env, ir_where_alloc where_alloc)
+{
+       switch (where_alloc) {
+       case stack_alloc: write_symbol(env, "stack_alloc"); return;
+       case heap_alloc:  write_symbol(env, "heap_alloc");  return;
+       }
+       panic("invalid where_alloc value");
+}
+
+static void write_throws(write_env_t *env, bool throws)
+{
+       write_symbol(env, throws ? "throw" : "nothrow");
+}
+
+static void write_list_begin(write_env_t *env)
 {
        fputs("[", env->file);
 }
 
-static void write_list_end(io_env_t *env)
+static void write_list_end(write_env_t *env)
 {
        fputs("] ", env->file);
 }
 
-static void write_initializer(io_env_t *env, ir_initializer_t *ini)
+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);
+}
+
+static void write_node_ref(write_env_t *env, const ir_node *node)
+{
+       write_long(env, get_irn_node_nr(node));
+}
+
+static void write_initializer(write_env_t *env, ir_initializer_t *ini)
 {
        FILE *f = env->file;
        ir_initializer_kind_t ini_kind = get_initializer_kind(ini);
@@ -425,273 +535,356 @@ static void write_initializer(io_env_t *env, ir_initializer_t *ini)
 
        switch (ini_kind) {
        case IR_INITIALIZER_CONST:
-               write_long(env, get_irn_node_nr(get_initializer_const_value(ini)));
-               break;
+               write_node_ref(env, get_initializer_const_value(ini));
+               return;
 
        case IR_INITIALIZER_TARVAL:
                write_tarval(env, get_initializer_tarval_value(ini));
-               break;
+               return;
 
        case IR_INITIALIZER_NULL:
-               break;
+               return;
 
        case IR_INITIALIZER_COMPOUND: {
                size_t i, n = get_initializer_compound_n_entries(ini);
-               ir_fprintf(f, "%zu ", n);
+               write_size_t(env, n);
                for (i = 0; i < n; ++i)
                        write_initializer(env, get_initializer_compound_value(ini, i));
-               break;
+               return;
        }
-
-       default:
-               panic("Unknown initializer kind");
        }
+       panic("Unknown initializer kind");
 }
 
-static void write_pin_state(io_env_t *env, ir_node *irn)
+static void write_pin_state(write_env_t *env, op_pin_state state)
 {
-       fputs(get_op_pin_state_name(get_irn_pinned(irn)), env->file);
+       fputs(get_op_pin_state_name(state), env->file);
        fputc(' ', env->file);
 }
 
-static void write_volatility(io_env_t *env, ir_volatility vol)
+static void write_volatility(write_env_t *env, ir_volatility vol)
 {
        fputs(get_volatility_name(vol), env->file);
        fputc(' ', env->file);
 }
 
-static void export_type_common(io_env_t *env, ir_type *tp)
+static void write_inline_property(write_env_t *env, irg_inline_property prop)
 {
-       fprintf(env->file, "\ttype %ld %s %u %u %s %u ",
-               get_type_nr(tp),
-               get_type_tpop_name(tp),
-               get_type_size_bytes(tp),
-               get_type_alignment_bytes(tp),
-               get_type_state_name(get_type_state(tp)),
-               tp->flags);
+       fputs(get_irg_inline_property_name(prop), env->file);
+       fputc(' ', env->file);
 }
 
-static void export_type_pre(io_env_t *env, ir_type *tp)
+static void write_type_state(write_env_t *env, ir_type_state state)
 {
-       FILE *f = env->file;
+       fputs(get_type_state_name(state), env->file);
+       fputc(' ', env->file);
+}
 
-       /* skip types to be handled by post walker */
-       switch (get_type_tpop_code(tp)) {
-       case tpo_array:
-       case tpo_method:
-       case tpo_pointer:
-               return;
-       default:
-               break;
-       }
+static void write_visibility(write_env_t *env, ir_visibility visibility)
+{
+       fputs(get_visibility_name(visibility), env->file);
+       fputc(' ', env->file);
+}
 
-       export_type_common(env, tp);
+static void write_mode_arithmetic(write_env_t *env, ir_mode_arithmetic arithmetic)
+{
+       fputs(get_mode_arithmetic_name(arithmetic), env->file);
+       fputc(' ', env->file);
+}
 
-       switch (get_type_tpop_code(tp)) {
-       case tpo_uninitialized:
-               panic("invalid type found");
+static void write_type(write_env_t *env, ir_type *tp);
+static void write_entity(write_env_t *env, ir_entity *entity);
 
-       case tpo_class:
-               write_ident_null(env, get_compound_ident(tp));
-               break;
+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));
+       write_symbol(env, get_type_tpop_name(tp));
+       write_unsigned(env, get_type_size_bytes(tp));
+       write_unsigned(env, get_type_alignment_bytes(tp));
+       write_type_state(env, get_type_state(tp));
+       write_unsigned(env, tp->flags);
+}
 
-       case tpo_primitive:
-               write_mode(env, get_type_mode(tp));
-               break;
+static void write_type_primitive(write_env_t *env, ir_type *tp)
+{
+       ir_type *base_type = get_primitive_base_type(tp);
 
-       case tpo_union:
-       case tpo_struct:
-       case tpo_enumeration:
-               write_ident_null(env, get_compound_ident(tp));
-               break;
+       if (base_type != NULL)
+               write_type(env, base_type);
 
-       case tpo_array:
-       case tpo_method:
-       case tpo_pointer:
-       case tpo_code:
-       case tpo_none:
-       case tpo_unknown:
-               break;
-       }
-       fputc('\n', f);
+       write_type_common(env, tp);
+       write_mode_ref(env, get_type_mode(tp));
+       if (base_type == NULL)
+               base_type = firm_none_type;
+       write_type_ref(env, base_type);
+       fputc('\n', env->file);
 }
 
-static void export_type_post(io_env_t *env, ir_type *tp)
+static void write_type_compound(write_env_t *env, ir_type *tp)
 {
-       FILE *f = env->file;
+       size_t n_members = get_compound_n_members(tp);
        size_t i;
 
-       /* skip types already handled by pre walker */
-       switch (get_type_tpop_code(tp)) {
-       case tpo_class:
-       case tpo_primitive:
-       case tpo_struct:
-       case tpo_union:
-       case tpo_unknown:
-       case tpo_uninitialized:
-       case tpo_code:
-       case tpo_none:
-               return;
-       case tpo_array:
-       case tpo_method:
-       case tpo_pointer:
-       case tpo_enumeration:
-               break;
+       if (is_Class_type(tp)) {
+               if (get_class_n_subtypes(tp) > 0 || get_class_n_supertypes(tp) > 0
+                   || get_class_type_info(tp) != NULL || get_class_vtable_size(tp) > 0) {
+                       /* sub/superclass export not implemented yet, it's unclear wether
+                        * class types will stay in libfirm anyway */
+                       panic("can't export class types yet");
+               }
        }
+       write_type_common(env, tp);
+       write_ident_null(env, get_compound_ident(tp));
+       fputc('\n', env->file);
 
-       export_type_common(env, tp);
-
-       switch (get_type_tpop_code(tp)) {
-       case tpo_array: {
-               size_t n = get_array_n_dimensions(tp);
-               ir_fprintf(f, "%zu %ld ", n, get_type_nr(get_array_element_type(tp)));
-               for (i = 0; i < n; i++) {
-                       ir_node *lower = get_array_lower_bound(tp, i);
-                       ir_node *upper = get_array_upper_bound(tp, i);
-
-                       if (is_Const(lower))
-                               write_long(env, get_tarval_long(get_Const_tarval(lower)));
-                       else
-                               panic("Lower array bound is not constant");
-
-                       if (is_Const(upper))
-                               write_long(env, get_tarval_long(get_Const_tarval(upper)));
-                       else if (is_Unknown(upper))
-                               fputs("unknown ", f);
-                       else
-                               panic("Upper array bound is not constant");
-               }
-               break;
+       for (i = 0; i < n_members; ++i) {
+               ir_entity *member = get_compound_member(tp, i);
+               write_entity(env, member);
        }
+}
 
-       case tpo_method: {
-               size_t nparams  = get_method_n_params(tp);
-               size_t nresults = get_method_n_ress(tp);
-               ir_fprintf(f, "%u %u %zu %zu ", get_method_calling_convention(tp),
-                       get_method_additional_properties(tp), nparams, nresults);
-               for (i = 0; i < nparams; i++)
-                       write_long(env, get_type_nr(get_method_param_type(tp, i)));
-               for (i = 0; i < nresults; i++)
-                       write_long(env, get_type_nr(get_method_res_type(tp, i)));
-               ir_fprintf(f, "%u ", get_method_variadicity(tp));
-               break;
+static void write_type_array(write_env_t *env, ir_type *tp)
+{
+       size_t     n_dimensions   = get_array_n_dimensions(tp);
+       ir_type   *element_type   = get_array_element_type(tp);
+       ir_entity *element_entity = get_array_element_entity(tp);
+       size_t   i;
+
+       write_type(env, element_type);
+
+       write_type_common(env, tp);
+       write_size_t(env, n_dimensions);
+       write_type_ref(env, get_array_element_type(tp));
+       for (i = 0; i < n_dimensions; i++) {
+               ir_node *lower = get_array_lower_bound(tp, i);
+               ir_node *upper = get_array_upper_bound(tp, i);
+
+               if (is_Const(lower))
+                       write_long(env, get_tarval_long(get_Const_tarval(lower)));
+               else
+                       panic("Lower array bound is not constant");
+
+               if (is_Const(upper))
+                       write_long(env, get_tarval_long(get_Const_tarval(upper)));
+               else if (is_Unknown(upper))
+                       write_symbol(env, "unknown");
+               else
+                       panic("Upper array bound is not constant");
        }
+       /* note that we just write a reference to the element entity
+        * but never the entity itself */
+       write_entity_ref(env, element_entity);
+       fputc('\n', env->file);
+}
 
-       case tpo_pointer:
-               write_mode(env, get_type_mode(tp));
-               write_long(env, get_type_nr(get_pointer_points_to_type(tp)));
-               break;
+static void write_type_method(write_env_t *env, ir_type *tp)
+{
+       size_t nparams  = get_method_n_params(tp);
+       size_t nresults = get_method_n_ress(tp);
+       size_t i;
 
-       case tpo_enumeration:
-               fprintf(stderr, "Enumeration type not handled yet by exporter\n");
-               break;
+       for (i = 0; i < nparams; i++)
+               write_type(env, get_method_param_type(tp, i));
+       for (i = 0; i < nresults; i++)
+               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);
+       for (i = 0; i < nparams; i++)
+               write_type_ref(env, get_method_param_type(tp, i));
+       for (i = 0; i < nresults; i++)
+               write_type_ref(env, get_method_res_type(tp, i));
+       write_unsigned(env, get_method_variadicity(tp));
+       fputc('\n', env->file);
+}
 
-       default:
-               printf("export_type: Unknown type code \"%s\".\n",
-                      get_type_tpop_name(tp));
-               break;
+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_mode_ref(env, get_type_mode(tp));
+       write_type_ref(env, points_to);
+       fputc('\n', env->file);
+}
+
+static void write_type_enumeration(write_env_t *env, ir_type *tp)
+{
+       write_type_common(env, tp);
+       write_ident_null(env, get_enumeration_ident(tp));
+       fputc('\n', env->file);
+}
+
+static void write_type(write_env_t *env, ir_type *tp)
+{
+       if (type_visited(tp))
+               return;
+       mark_type_visited(tp);
+
+       switch ((tp_opcode)get_type_tpop_code(tp)) {
+       case tpo_none:
+       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:
+               write_type_compound(env, tp);
+               return;
+
+       case tpo_primitive:    write_type_primitive(env, tp);   return;
+       case tpo_enumeration:  write_type_enumeration(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;
        }
-       fputc('\n', f);
+       panic("can't write invalid type %+F\n", tp);
 }
 
-static void export_entity(io_env_t *env, ir_entity *ent)
+static void write_entity(write_env_t *env, ir_entity *ent)
 {
-       FILE          *file       = env->file;
+       ir_type       *type       = get_entity_type(ent);
        ir_type       *owner      = get_entity_owner(ent);
        ir_visibility  visibility = get_entity_visibility(ent);
        ir_linkage     linkage    = get_entity_linkage(ent);
 
-       /* we don't dump array_element_ent entities. They're a strange concept
-        * and lead to cycles in type_graph.
-        */
-       if (is_Array_type(owner))
+       if (entity_visited(ent))
                return;
+       mark_entity_visited(ent);
 
-       fprintf(env->file, "\tentity ");
-       write_long(env, get_entity_nr(ent));
-       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));
+       write_type(env, type);
+       write_type(env, owner);
+
+       fputc('\t', env->file);
+       switch ((ir_entity_kind)ent->entity_kind) {
+       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;
        }
+       write_long(env, get_entity_nr(ent));
 
-       /* visibility + linkage */
-       if (visibility != ir_visibility_default) {
-               fprintf(file, "%s ", get_visibility_name(visibility));
+       if (ent->entity_kind != IR_ENTITY_LABEL
+           && ent->entity_kind != IR_ENTITY_PARAMETER) {
+               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));
+               }
        }
+
+       write_visibility(env, visibility);
+       write_list_begin(env);
        if (linkage & IR_LINKAGE_CONSTANT)
-               fputs("constant ", file);
+               write_symbol(env, "constant");
        if (linkage & IR_LINKAGE_WEAK)
-               fputs("weak ", file);
+               write_symbol(env, "weak");
        if (linkage & IR_LINKAGE_GARBAGE_COLLECT)
-               fputs("garbage_collect ", file);
+               write_symbol(env, "garbage_collect");
        if (linkage & IR_LINKAGE_MERGE)
-               fputs("merge ", file);
+               write_symbol(env, "merge");
        if (linkage & IR_LINKAGE_HIDDEN_USER)
-               fputs("hidden_user ", file);
-
-       fprintf(file, "%ld %ld %d %u %d %s ",
-                       get_type_nr(get_entity_type(ent)),
-                       get_type_nr(owner),
-                       get_entity_offset(ent),
-                       (unsigned) get_entity_offset_bits_remainder(ent),
-                       is_entity_compiler_generated(ent),
-                       get_volatility_name(get_entity_volatility(ent)));
-
-       if (ent->initializer != NULL) {
-               fputs("initializer ", env->file);
-               write_initializer(env, get_entity_initializer(ent));
-       } else if (entity_has_compound_ent_values(ent)) {
-               size_t i, n = get_compound_ent_n_values(ent);
-               fputs("compoundgraph ", env->file);
-               ir_fprintf(env->file, "%zu ", n);
-               for (i = 0; i < n; i++) {
-                       ir_entity *member = get_compound_ent_value_member(ent, i);
-                       ir_node   *irn    = get_compound_ent_value(ent, i);
-                       fprintf(env->file, "%ld %ld ", get_entity_nr(member), get_irn_node_nr(irn));
+               write_symbol(env, "hidden_user");
+       write_list_end(env);
+
+       write_type_ref(env, type);
+       if (ent->entity_kind != IR_ENTITY_LABEL)
+               write_type_ref(env, owner);
+       write_long(env, is_entity_compiler_generated(ent));
+       write_volatility(env, get_entity_volatility(ent));
+
+       switch ((ir_entity_kind)ent->entity_kind) {
+       case IR_ENTITY_NORMAL:
+               if (ent->initializer != NULL) {
+                       write_symbol(env, "initializer");
+                       write_initializer(env, get_entity_initializer(ent));
+               } else if (entity_has_compound_ent_values(ent)) {
+                       /* compound graph API is deprecated */
+                       panic("exporting compound_graph initializers not supported");
+               } else {
+                       write_symbol(env, "none");
                }
-       } else {
-               fputs("none", env->file);
+               break;
+       case IR_ENTITY_COMPOUND_MEMBER:
+               write_long(env, get_entity_offset(ent));
+               write_unsigned(env, get_entity_offset_bits_remainder(ent));
+               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);
+               }
+               break;
+       }
+       case IR_ENTITY_LABEL:
+       case IR_ENTITY_METHOD:
+               break;
        }
 
        fputc('\n', env->file);
 }
 
-static void export_type_or_ent_pre(type_or_ent tore, void *ctx)
+static void write_switch_table(write_env_t *env, const ir_switch_table *table)
 {
-       io_env_t *env = (io_env_t *) ctx;
-       if (get_kind(tore.typ) == k_type)
-               export_type_pre(env, tore.typ);
+       size_t n_entries = ir_switch_table_get_n_entries(table);
+       size_t i;
+
+       write_size_t(env, n_entries);
+       for (i = 0; i < n_entries; ++i) {
+               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);
+               write_tarval(env, min);
+               write_tarval(env, max);
+       }
 }
 
-static void export_type_or_ent_post(type_or_ent tore, void *ctx)
+static void write_pred_refs(write_env_t *env, const ir_node *node, int from)
 {
-       io_env_t *env = (io_env_t *) ctx;
-
-       switch (get_kind(tore.ent)) {
-       case k_entity:
-               export_entity(env, tore.ent);
-               break;
-
-       case k_type:
-               export_type_post(env, tore.typ);
-               break;
-
-       default:
-               panic("export_type_or_ent_post: Unknown type or entity.");
+       int arity = get_irn_arity(node);
+       int i;
+       write_list_begin(env);
+       assert(from <= arity);
+       for (i = from; i < arity; ++i) {
+               ir_node *pred = get_irn_n(node, i);
+               write_node_ref(env, pred);
        }
+       write_list_end(env);
 }
 
-static void export_ASM(io_env_t *env, ir_node *node)
+static void write_node_nr(write_env_t *env, const ir_node *node)
+{
+       write_long(env, get_irn_node_nr(node));
+}
+
+static void write_ASM(write_env_t *env, const ir_node *node)
 {
        ir_asm_constraint *input_constraints    = get_ASM_input_constraints(node);
        ir_asm_constraint *output_constraints   = get_ASM_output_constraints(node);
        ident            **clobbers             = get_ASM_clobbers(node);
-       int                n_input_constraints  = get_ASM_n_input_constraints(node);
-       int                n_output_constraints = get_ASM_n_output_constraints(node);
-       int                n_clobbers           = get_ASM_n_clobbers(node);
-       int i;
+       size_t             n_input_constraints  = get_ASM_n_input_constraints(node);
+       size_t             n_output_constraints = get_ASM_n_output_constraints(node);
+       size_t             n_clobbers           = get_ASM_n_clobbers(node);
+       size_t             i;
+
+       write_symbol(env, "ASM");
+       write_node_nr(env, node);
+       write_node_nr(env, get_nodes_block(node));
 
        write_ident(env, get_ASM_text(node));
        write_list_begin(env);
@@ -699,7 +892,7 @@ static void export_ASM(io_env_t *env, ir_node *node)
                const ir_asm_constraint *constraint = &input_constraints[i];
                write_unsigned(env, constraint->pos);
                write_ident(env, constraint->constraint);
-               write_mode(env, constraint->mode);
+               write_mode_ref(env, constraint->mode);
        }
        write_list_end(env);
 
@@ -708,7 +901,7 @@ static void export_ASM(io_env_t *env, ir_node *node)
                const ir_asm_constraint *constraint = &output_constraints[i];
                write_unsigned(env, constraint->pos);
                write_ident(env, constraint->constraint);
-               write_mode(env, constraint->mode);
+               write_mode_ref(env, constraint->mode);
        }
        write_list_end(env);
 
@@ -718,217 +911,308 @@ static void export_ASM(io_env_t *env, ir_node *node)
                write_ident(env, clobber);
        }
        write_list_end(env);
+
+       write_pin_state(env, get_irn_pinned(node));
+       write_pred_refs(env, node, 0);
 }
 
-/**
- * Walker: exports every node.
- */
-static void export_node(ir_node *irn, void *ctx)
+static void write_Phi(write_env_t *env, const ir_node *node)
 {
-       io_env_t *env = (io_env_t *) ctx;
-       int i, n;
-       unsigned opcode = get_irn_opcode(irn);
-
-       if (env->ignoreblocks && opcode == iro_Block)
-               return;
+       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));
+       write_pred_refs(env, node, 0);
+}
 
-       fprintf(env->file, "\t%s ", get_irn_opname(irn));
-       write_long(env, get_irn_node_nr(irn));
+static void write_Block(write_env_t *env, const ir_node *node)
+{
+       ir_entity *entity = get_Block_entity(node);
 
-       write_list_begin(env);
-       n = get_irn_arity(irn);
-       if (!is_Block(irn)) {
-               ir_node *block = get_nodes_block(irn);
-               write_long(env, get_irn_node_nr(block));
+       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);
        }
+       write_pred_refs(env, node, 0);
+}
 
-       for (i = 0; i < n; i++) {
-               ir_node *pred = get_irn_n(irn, i);
-               if (pred == NULL) {
-                       /* Anchor node may have NULL predecessors */
-                       assert(is_Anchor(irn));
-                       fputs("-1 ", env->file);
-               } else {
-                       write_long(env, get_irn_node_nr(pred));
-               }
+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);
+}
+
+static void write_SymConst(write_env_t *env, const ir_node *node)
+{
+       /* TODO: only symconst_addr_ent implemented yet */
+       if (get_SymConst_kind(node) != symconst_addr_ent)
+               panic("Can't export %+F (only symconst_addr_ent supported)", node);
+
+       write_symbol(env, "SymConst");
+       write_node_nr(env, node);
+       write_mode_ref(env, get_irn_mode(node));
+       write_entity_ref(env, get_SymConst_entity(node));
+}
+
+typedef void (*write_node_func)(write_env_t *env, const ir_node *node);
+
+static void register_node_writer(ir_op *op, write_node_func func)
+{
+       set_generic_function_ptr(op, (op_func)func);
+}
+
+static void writers_init(void)
+{
+       clear_irp_opcodes_generic_func();
+       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);
+       register_node_writer(op_SymConst, write_SymConst);
+       register_generated_node_writers();
+}
+
+static void write_node(const ir_node *node, write_env_t *env)
+{
+       ir_op          *op   = get_irn_op(node);
+       write_node_func func = (write_node_func) get_generic_function_ptr(op);
+
+       fputc('\t', env->file);
+       if (func == NULL)
+               panic("No write_node_func for %+F", node);
+       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)
+{
+       int arity = get_irn_arity(node);
+       int i;
+       for (i = 0; i < arity; ++i) {
+               ir_node *pred = get_irn_n(node, i);
+               write_node_recursive(pred, env);
        }
-       write_list_end(env);
+}
 
-       fputs("{ ", env->file);
+/**
+ * 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;
 
-       switch (opcode) {
-       case iro_Start:
-       case iro_End:
-       case iro_Block:
-       case iro_Anchor:
-               break;
-       case iro_SymConst:
-               /* TODO: only symconst_addr_ent implemented yet */
-               assert(get_SymConst_kind(irn) == symconst_addr_ent);
-               fprintf(env->file, "%ld ", get_entity_nr(get_SymConst_entity(irn)));
-               write_mode(env, get_irn_mode(irn));
-               break;
-       case iro_Proj:
-               write_mode(env, get_irn_mode(irn));
-               fprintf(env->file, "%ld ", get_Proj_proj(irn));
-               break;
-       case iro_ASM:
-               export_ASM(env, irn);
-               break;
-#include "gen_irio_export.inl"
-       default:
-               panic("no export code for node %+F\n", irn);
+       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 {
+               int arity = get_irn_arity(node);
+               int i;
+               for (i = 0; i < arity; ++i) {
+                       ir_node *pred = get_irn_n(node, i);
+                       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));
+               write_int(env, get_mode_sign(mode));
+               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));
+
+               write_mode_ref(env, get_reference_mode_signed_eq(mode));
+               write_mode_ref(env, get_reference_mode_unsigned_eq(mode));
+               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));
+       } else {
+               panic("Can't write internal modes");
        }
-       fputs("}\n", env->file);
 }
 
-static void export_modes(io_env_t *env)
+static void write_modes(write_env_t *env)
 {
        size_t i, n_modes = get_irp_n_modes();
 
-       fputs("modes {\n", env->file);
+       write_symbol(env, "modes");
+       fputs("{\n", env->file);
 
        for (i = 0; i < n_modes; i++) {
                ir_mode *mode = get_irp_mode(i);
-
-               if (mode_is_int(mode)) {
-                       fprintf(env->file, "\tint_mode ");
-                       write_string(env, get_mode_name(mode));
-                       fprintf(env->file, "%s %u %d %u ",
-                               get_mode_arithmetic_name(get_mode_arithmetic(mode)),
-                               get_mode_size_bits(mode), get_mode_sign(mode),
-                               get_mode_modulo_shift(mode));
-               } else if (mode_is_reference(mode)) {
-                       fprintf(env->file, "\treference_mode ");
-                       write_string(env, get_mode_name(mode));
-                       fprintf(env->file, "%s %u %u ",
-                                       get_mode_arithmetic_name(get_mode_arithmetic(mode)),
-                                       get_mode_size_bits(mode),
-                                       get_mode_modulo_shift(mode));
-                       write_mode(env, get_reference_mode_signed_eq(mode));
-                       write_mode(env, get_reference_mode_unsigned_eq(mode));
-                       write_int(env, (mode == mode_P ? 1 : 0));
-               } else if (mode_is_float(mode)) {
-                       fprintf(env->file, "\tfloat_mode ");
-                       write_string(env, get_mode_name(mode));
-                       fprintf(env->file, "%s %u %u ",
-                               get_mode_arithmetic_name(get_mode_arithmetic(mode)),
-                               get_mode_exponent_size(mode),
-                               get_mode_mantissa_size(mode));
-               } else {
-                       /* skip "internal" modes */
+               if (!mode_is_int(mode) && !mode_is_reference(mode)
+                   && !mode_is_float(mode)) {
+                   /* skip internal modes */
+                   continue;
                }
+               fputc('\t', env->file);
+               write_mode(env, mode);
                fputc('\n', env->file);
        }
 
-       fputs("}\n", env->file);
+       fputs("}\n\n", env->file);
 }
 
-static void export_program(io_env_t *env)
+static void write_program(write_env_t *env)
 {
-       FILE         *f = env->file;
-       ir_segment_t  s;
+       ir_segment_t s;
+       size_t n_asms = get_irp_n_asms();
+       size_t i;
 
-       fputs("\nprogram {\n", f);
+       write_symbol(env, "program");
+       write_scope_begin(env);
        if (irp_prog_name_is_set()) {
-               fprintf(f, "\tname ");
+               fputc('\t', env->file);
+               write_symbol(env, "name");
                write_string(env, get_irp_name());
-               fputc('\n', f);
+               fputc('\n', env->file);
        }
 
        for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
                ir_type *segment_type = get_segment_type(s);
-               fprintf(f, "\tsegment_type %s ", get_segment_name(s));
+               fputc('\t', env->file);
+               write_symbol(env, "segment_type");
+               write_symbol(env, get_segment_name(s));
                if (segment_type == NULL) {
-                       fputs(" NULL\n", f);
+                       write_symbol(env, "NULL");
                } else {
-                       write_long(env, get_type_nr(segment_type));
-                       fputc('\n', f);
+                       write_type_ref(env, segment_type);
                }
+               fputc('\n', env->file);
+       }
+
+       for (i = 0; i < n_asms; ++i) {
+               ident *asm_text = get_irp_asm(i);
+               fputc('\t', env->file);
+               write_symbol(env, "asm");
+               write_ident(env, asm_text);
+               fputc('\n', env->file);
        }
-       fputs("}\n", f);
+       write_scope_end(env);
 }
 
-void ir_export(const char *filename)
+int ir_export(const char *filename)
 {
        FILE *file = fopen(filename, "wt");
+       int   res  = 0;
        if (file == NULL) {
                perror(filename);
-               return;
+               return 1;
        }
 
-       ir_export_file(file, filename);
-       fclose(file);
+       ir_export_file(file);
+       res = ferror(file);
+       fclose(file);
+       return res;
+}
+
+static void write_node_cb(ir_node *node, void *ctx)
+{
+       write_env_t *env = (write_env_t*)ctx;
+       write_node(node, env);
+}
+
+static void write_typegraph(write_env_t *env)
+{
+       size_t n_types = get_irp_n_types();
+       size_t i;
+
+       write_symbol(env, "typegraph");
+       write_scope_begin(env);
+       irp_reserve_resources(irp, IRP_RESOURCE_TYPE_VISITED);
+       inc_master_type_visited();
+       for (i = 0; i < n_types; ++i) {
+               ir_type *type = get_irp_type(i);
+               write_type(env, type);
+       }
+       irp_free_resources(irp, IRP_RESOURCE_TYPE_VISITED);
+       write_scope_end(env);
+}
+
+static void write_irg(write_env_t *env, ir_graph *irg)
+{
+       write_symbol(env, "irg");
+       write_entity_ref(env, get_irg_entity(irg));
+       write_type_ref(env, get_irg_frame_type(irg));
+       write_inline_property(env, get_irg_inline_property(irg));
+       write_unsigned(env, get_irg_additional_properties(irg));
+       write_scope_begin(env);
+       ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
+       inc_irg_visited(irg);
+       assert(pdeq_empty(env->write_queue));
+       pdeq_putr(env->write_queue, irg->anchor);
+       do {
+               ir_node *node = (ir_node*) pdeq_getl(env->write_queue);
+               write_node_recursive(node, env);
+       } while (!pdeq_empty(env->write_queue));
+       ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
+       write_scope_end(env);
 }
 
 /* Exports the whole irp to the given file in a textual form. */
-void ir_export_file(FILE *file, const char *outputname)
+void ir_export_file(FILE *file)
 {
-       io_env_t env;
+       write_env_t my_env;
+       write_env_t *env = &my_env;
        size_t i, n_irgs = get_irp_n_irgs();
 
-       (void) outputname;
-       env.file = file;
+       memset(env, 0, sizeof(*env));
+       env->file        = file;
+       env->write_queue = new_pdeq();
 
-       export_modes(&env);
+       writers_init();
+       write_modes(env);
 
-       fputs("\ntypegraph {\n", env.file);
-       type_walk_prog(export_type_or_ent_pre, export_type_or_ent_post, &env);
-       fputs("}\n", env.file);
+       write_typegraph(env);
 
        for (i = 0; i < n_irgs; i++) {
-               ir_graph *irg       = get_irp_irg(i);
-
-               fprintf(env.file, "\nirg %ld %ld {\n",
-                       get_entity_nr(get_irg_entity(irg)),
-                       get_type_nr(get_irg_frame_type(irg)));
-
-               env.ignoreblocks = 0;
-               irg_block_walk_graph(irg, NULL, export_node, &env);
-
-               env.ignoreblocks = 1;
-               irg_walk_anchors(irg, NULL, export_node, &env);
-
-               fputs("}\n", env.file);
+               ir_graph *irg = get_irp_irg(i);
+               write_irg(env, irg);
        }
 
-       fprintf(env.file, "\nconstirg %ld {\n", get_irn_node_nr(get_const_code_irg()->current_block));
+       write_symbol(env, "constirg");
+       write_node_ref(env, get_const_code_irg()->current_block);
+       write_scope_begin(env);
+       walk_const_code(NULL, write_node_cb, env);
+       write_scope_end(env);
 
-       walk_const_code(NULL, export_node, &env);
-       fputs("}\n", env.file);
+       write_program(env);
 
-       export_program(&env);
+       del_pdeq(env->write_queue);
 }
 
-/* Exports the given irg to the given file. */
-void ir_export_irg(ir_graph *irg, FILE *file, const char *outputname)
-{
-       io_env_t env;
-
-       (void) outputname;
-       env.file = file;
-
-       export_modes(&env);
-
-       fputs("typegraph {\n", env.file);
-
-       type_walk_irg(irg, export_type_or_ent_pre, export_type_or_ent_post, &env);
-
-       fprintf(env.file, "}\n\nirg %ld {\n", get_entity_nr(get_irg_entity(irg)));
 
-       env.ignoreblocks = 0;
-       irg_block_walk_graph(irg, NULL, export_node, &env);
 
-       env.ignoreblocks = 1;
-       irg_walk_anchors(irg, NULL, export_node, &env);
-
-       /* TODO: Only output needed constants */
-       fprintf(env.file, "}\n\nconstirg %ld {\n", get_irn_node_nr(get_const_code_irg()->current_block));
-       walk_const_code(NULL, export_node, &env);
-       fputs("}\n", env.file);
-}
-
-static void read_c(io_env_t *env)
+static void read_c(read_env_t *env)
 {
        int c = fgetc(env->file);
        env->c = c;
@@ -937,7 +1221,7 @@ static void read_c(io_env_t *env)
 }
 
 /** Returns the first non-whitespace character or EOF. **/
-static void skip_ws(io_env_t *env)
+static void skip_ws(read_env_t *env)
 {
        while (true) {
                switch (env->c) {
@@ -954,28 +1238,28 @@ static void skip_ws(io_env_t *env)
        }
 }
 
-static void skip_to(io_env_t *env, char to_ch)
+static void skip_to(read_env_t *env, char to_ch)
 {
        while (env->c != to_ch && env->c != EOF) {
                read_c(env);
        }
 }
 
-static int expect_char(io_env_t *env, char ch)
+static bool expect_char(read_env_t *env, char ch)
 {
        skip_ws(env);
        if (env->c != ch) {
                parse_error(env, "Unexpected char '%c', expected '%c'\n",
                            env->c, ch);
-               return 0;
+               return false;
        }
        read_c(env);
-       return 1;
+       return true;
 }
 
-#define EXPECT(c) if (expect_char(env, (c))) {} else return 0
+#define EXPECT(c) if (expect_char(env, (c))) {} else return
 
-static char *read_word(io_env_t *env)
+static char *read_word(read_env_t *env)
 {
        skip_ws(env);
 
@@ -1002,7 +1286,7 @@ endofword:
        return (char*)obstack_finish(&env->obst);
 }
 
-static char *read_string(io_env_t *env)
+static char *read_string(read_env_t *env)
 {
        skip_ws(env);
        if (env->c != '"') {
@@ -1043,7 +1327,7 @@ static char *read_string(io_env_t *env)
        return (char*)obstack_finish(&env->obst);
 }
 
-static ident *read_ident(io_env_t *env)
+static ident *read_ident(read_env_t *env)
 {
        char  *str = read_string(env);
        ident *res = new_id_from_str(str);
@@ -1051,10 +1335,18 @@ static ident *read_ident(io_env_t *env)
        return res;
 }
 
+static ident *read_symbol(read_env_t *env)
+{
+       char  *str = read_word(env);
+       ident *res = new_id_from_str(str);
+       obstack_free(&env->obst, str);
+       return res;
+}
+
 /*
  * reads a "quoted string" or alternatively the token NULL
  */
-static char *read_string_null(io_env_t *env)
+static char *read_string_null(read_env_t *env)
 {
        skip_ws(env);
        if (env->c == 'N') {
@@ -1071,7 +1363,7 @@ static char *read_string_null(io_env_t *env)
        exit(1);
 }
 
-static ident *read_ident_null(io_env_t *env)
+static ident *read_ident_null(read_env_t *env)
 {
        ident *res;
        char  *str = read_string_null(env);
@@ -1083,7 +1375,7 @@ static ident *read_ident_null(io_env_t *env)
        return res;
 }
 
-static long read_long(io_env_t *env)
+static long read_long(read_env_t *env)
 {
        long  result;
        char *str;
@@ -1108,23 +1400,23 @@ static long read_long(io_env_t *env)
        return result;
 }
 
-static int read_int(io_env_t *env)
+static int read_int(read_env_t *env)
 {
        return (int) read_long(env);
 }
 
-static unsigned read_unsigned(io_env_t *env)
+static unsigned read_unsigned(read_env_t *env)
 {
        return (unsigned) read_long(env);
 }
 
-static size_t read_size_t(io_env_t *env)
+static size_t read_size_t(read_env_t *env)
 {
        /* FIXME */
        return (size_t) read_unsigned(env);
 }
 
-static void expect_list_begin(io_env_t *env)
+static void expect_list_begin(read_env_t *env)
 {
        skip_ws(env);
        if (env->c != '[') {
@@ -1134,7 +1426,7 @@ static void expect_list_begin(io_env_t *env)
        read_c(env);
 }
 
-static bool list_has_next(io_env_t *env)
+static bool list_has_next(read_env_t *env)
 {
        if (feof(env->file)) {
                parse_error(env, "Unexpected EOF while reading list");
@@ -1149,67 +1441,104 @@ static bool list_has_next(io_env_t *env)
        return true;
 }
 
-static ir_node *get_node_or_null(io_env_t *env, long nodenr)
+static void *get_id(read_env_t *env, long id)
+{
+       id_entry key, *entry;
+       key.id = id;
+
+       entry = (id_entry*)set_find(env->idset, &key, sizeof(key), (unsigned) id);
+       return entry ? entry->elem : NULL;
+}
+
+static void set_id(read_env_t *env, long id, void *elem)
+{
+       id_entry key;
+       key.id = id;
+       key.elem = elem;
+       set_insert(env->idset, &key, sizeof(key), (unsigned) id);
+}
+
+static ir_node *get_node_or_null(read_env_t *env, long nodenr)
 {
        ir_node *node = (ir_node *) get_id(env, nodenr);
        if (node && node->kind != k_ir_node) {
-               panic("Irn ID %ld collides with something else in line %d\n",
-                     nodenr, env->line);
+               parse_error(env, "Irn ID %ld collides with something else\n",
+                           nodenr);
+               return NULL;
        }
        return node;
 }
 
-static ir_node *get_node_or_dummy(io_env_t *env, long nodenr)
+static ir_type *get_type(read_env_t *env, long typenr)
 {
-       ir_node *node = get_node_or_null(env, nodenr);
-       if (node == NULL) {
-               node = new_r_Dummy(env->irg, mode_X);
-               set_id(env, nodenr, node);
+       ir_type *type = (ir_type *) get_id(env, typenr);
+       if (type == NULL) {
+               parse_error(env, "Type %ld not defined (yet?)\n", typenr);
+               return firm_unknown_type;
        }
-       return node;
+       if (type->kind != k_type) {
+               parse_error(env, "Object %ld is not a type (but should be)\n", typenr);
+               return firm_unknown_type;
+       }
+       return type;
 }
 
-static ir_type *get_type(io_env_t *env, long typenr)
+static ir_type *read_type_ref(read_env_t *env)
 {
-       ir_type *type = (ir_type *) get_id(env, typenr);
-       if (type == NULL)
-               panic("unknown type: %ld in line %d\n", typenr, env->line);
-       else if (type->kind != k_type)
-               panic("type ID %ld collides with something else in line %d\n",
-                     typenr, env->line);
-       return type;
+       char *str = read_word(env);
+       if (strcmp(str, "none") == 0) {
+               obstack_free(&env->obst, str);
+               return firm_none_type;
+       }
+       if (strcmp(str, "unknown") == 0) {
+               obstack_free(&env->obst, str);
+               return firm_unknown_type;
+       }
+       if (strcmp(str, "code") == 0) {
+               obstack_free(&env->obst, str);
+               return firm_code_type;
+       }
+       long nr = atol(str);
+       obstack_free(&env->obst, str);
+
+       return get_type(env, nr);
 }
 
-static ir_type *read_type(io_env_t *env)
+static ir_entity *create_error_entity(void)
 {
-       return get_type(env, read_long(env));
+       ir_entity *res = new_entity(get_glob_type(), new_id_from_str("error"),
+                                   firm_unknown_type);
+       return res;
 }
 
-static ir_entity *get_entity(io_env_t *env, long entnr)
+static ir_entity *get_entity(read_env_t *env, long entnr)
 {
        ir_entity *entity = (ir_entity *) get_id(env, entnr);
        if (entity == NULL) {
                parse_error(env, "unknown entity: %ld\n", entnr);
-               exit(1);
-       } else if (entity->kind != k_entity) {
-               panic("Entity ID %ld collides with something else in line %d\n",
-                     entnr, env->line);
+               return create_error_entity();
+       }
+       if (entity->kind != k_entity) {
+               parse_error(env, "Object %ld is not an entity (but should be)\n",
+                           entnr);
+               return create_error_entity();
        }
 
        return entity;
 }
 
-static ir_entity *read_entity(io_env_t *env)
+static ir_entity *read_entity_ref(read_env_t *env)
 {
-       return get_entity(env, read_long(env));
+       long nr = read_long(env);
+       return get_entity(env, nr);
 }
 
-static ir_mode *read_mode(io_env_t *env)
+static ir_mode *read_mode_ref(read_env_t *env)
 {
-       char *str = read_string(env);
-       size_t i, n;
+       char  *str = read_string(env);
+       size_t n   = get_irp_n_modes();
+       size_t i;
 
-       n = get_irp_n_modes();
        for (i = 0; i < n; i++) {
                ir_mode *mode = get_irp_mode(i);
                if (strcmp(str, get_mode_name(mode)) == 0) {
@@ -1219,27 +1548,28 @@ static ir_mode *read_mode(io_env_t *env)
        }
 
        parse_error(env, "unknown mode \"%s\"\n", str);
-       exit(1);
+       return mode_ANY;
 }
 
 static const char *get_typetag_name(typetag_t typetag)
 {
        switch (typetag) {
-       case tt_align:              return "align";
-       case tt_allocation:         return "allocation";
-       case tt_builtin:            return "builtin kind";
-       case tt_cond_jmp_predicate: return "cond_jmp_predicate";
-       case tt_initializer:        return "initializer kind";
-       case tt_iro:                return "opcode";
-       case tt_keyword:            return "keyword";
-       case tt_linkage:            return "linkage";
-       case tt_mode_arithmetic:    return "mode_arithmetic";
-       case tt_pin_state:          return "pin state";
-       case tt_segment:            return "segment";
-       case tt_tpo:                return "type";
-       case tt_type_state:         return "type state";
-       case tt_volatility:         return "volatility";
-       case tt_visibility:         return "visibility";
+       case tt_align:               return "align";
+       case tt_builtin_kind:        return "builtin kind";
+       case tt_cond_jmp_predicate:  return "cond_jmp_predicate";
+       case tt_initializer:         return "initializer kind";
+       case tt_irg_inline_property: return "irg_inline_property";
+       case tt_keyword:             return "keyword";
+       case tt_linkage:             return "linkage";
+       case tt_mode_arithmetic:     return "mode_arithmetic";
+       case tt_pin_state:           return "pin state";
+       case tt_segment:             return "segment";
+       case tt_throws:              return "throws";
+       case tt_tpo:                 return "type";
+       case tt_type_state:          return "type state";
+       case tt_visibility:          return "visibility";
+       case tt_volatility:          return "volatility";
+       case tt_where_alloc:         return "where alloc";
        }
        return "<UNKNOWN>";
 }
@@ -1247,7 +1577,7 @@ static const char *get_typetag_name(typetag_t typetag)
 /**
  * Read and decode an enum constant.
  */
-static unsigned read_enum(io_env_t *env, typetag_t typetag)
+static unsigned read_enum(read_env_t *env, typetag_t typetag)
 {
        char     *str  = read_word(env);
        unsigned  code = symbol(str, typetag);
@@ -1261,40 +1591,131 @@ static unsigned read_enum(io_env_t *env, typetag_t typetag)
        return 0;
 }
 
-#define read_align(env)              ((ir_align)              read_enum(env, tt_align))
-#define read_allocation(env)         ((ir_allocation)         read_enum(env, tt_allocation))
-#define read_builtin_kind(env)       ((ir_builtin_kind)       read_enum(env, tt_builtin))
-#define read_cond_jmp_predicate(env) ((cond_jmp_predicate)    read_enum(env, tt_cond_jmp_predicate))
-#define read_initializer_kind(env)   ((ir_initializer_kind_t) read_enum(env, tt_initializer))
-#define read_mode_arithmetic(env)    ((ir_mode_arithmetic)    read_enum(env, tt_mode_arithmetic))
-#define read_peculiarity(env)        ((ir_peculiarity)        read_enum(env, tt_peculiarity))
-#define read_pin_state(env)          ((op_pin_state)          read_enum(env, tt_pin_state))
-#define read_type_state(env)         ((ir_type_state)         read_enum(env, tt_type_state))
-#define read_variability(env)        ((ir_variability)        read_enum(env, tt_variability))
-#define read_volatility(env)         ((ir_volatility)         read_enum(env, tt_volatility))
+static ir_align read_align(read_env_t *env)
+{
+       return (ir_align)read_enum(env, tt_align);
+}
+
+static ir_builtin_kind read_builtin_kind(read_env_t *env)
+{
+       return (ir_builtin_kind)read_enum(env, tt_builtin_kind);
+}
+
+static cond_jmp_predicate read_cond_jmp_predicate(read_env_t *env)
+{
+       return (cond_jmp_predicate)read_enum(env, tt_cond_jmp_predicate);
+}
+
+static ir_initializer_kind_t read_initializer_kind(read_env_t *env)
+{
+       return (ir_initializer_kind_t)read_enum(env, tt_initializer);
+}
+
+static ir_mode_arithmetic read_mode_arithmetic(read_env_t *env)
+{
+       return (ir_mode_arithmetic)read_enum(env, tt_mode_arithmetic);
+}
+
+static op_pin_state read_pin_state(read_env_t *env)
+{
+       return (op_pin_state)read_enum(env, tt_pin_state);
+}
+
+static ir_type_state read_type_state(read_env_t *env)
+{
+       return (ir_type_state)read_enum(env, tt_type_state);
+}
+
+static ir_visibility read_visibility(read_env_t *env)
+{
+       return (ir_visibility)read_enum(env, tt_visibility);
+}
+
+static ir_linkage read_linkage(read_env_t *env)
+{
+       return (ir_linkage)read_enum(env, tt_linkage);
+}
+
+static ir_volatility read_volatility(read_env_t *env)
+{
+       return (ir_volatility)read_enum(env, tt_volatility);
+}
+
+static ir_where_alloc read_where_alloc(read_env_t *env)
+{
+       return (ir_where_alloc)read_enum(env, tt_where_alloc);
+}
 
-static ir_tarval *read_tv(io_env_t *env)
+static bool read_throws(read_env_t *env)
 {
-       ir_mode   *tvmode = read_mode(env);
+       return (bool)read_enum(env, tt_throws);
+}
+
+static keyword_t read_keyword(read_env_t *env)
+{
+       return (keyword_t)read_enum(env, tt_keyword);
+}
+
+static irg_inline_property read_inline_property(read_env_t *env)
+{
+       return (irg_inline_property)read_enum(env, tt_irg_inline_property);
+}
+
+static ir_relation read_relation(read_env_t *env)
+{
+       return (ir_relation)read_long(env);
+}
+
+static ir_tarval *read_tarval(read_env_t *env)
+{
+       ir_mode   *tvmode = read_mode_ref(env);
        char      *str    = read_word(env);
-       ir_tarval *tv     = new_tarval_from_str(str, strlen(str), tvmode);
+       ir_tarval *tv;
+       if (strcmp(str, "bad") == 0)
+               return tarval_bad;
+       tv = new_tarval_from_str(str, strlen(str), tvmode);
+       if (tv == tarval_bad)
+               parse_error(env, "problem while parsing tarval '%s'\n", str);
        obstack_free(&env->obst, str);
 
        return tv;
 }
 
-static ir_initializer_t *read_initializer(io_env_t *env)
+static ir_switch_table *read_switch_table(read_env_t *env)
+{
+       size_t           n_entries = read_size_t(env);
+       ir_switch_table *table     = ir_new_switch_table(env->irg, n_entries);
+       size_t           i;
+
+       for (i = 0; i < n_entries; ++i) {
+               long       pn  = read_long(env);
+               ir_tarval *min = read_tarval(env);
+               ir_tarval *max = read_tarval(env);
+               ir_switch_table_set(table, i, min, max, pn);
+       }
+       return table;
+}
+
+static ir_initializer_t *read_initializer(read_env_t *env)
 {
        ir_initializer_kind_t ini_kind = read_initializer_kind(env);
 
        switch (ini_kind) {
        case IR_INITIALIZER_CONST: {
-               ir_node *irn = get_node_or_dummy(env, read_long(env));
-               return create_initializer_const(irn);
+               long nr = read_long(env);
+               ir_node *node = get_node_or_null(env, nr);
+               ir_initializer_t *initializer = create_initializer_const(node);
+               if (node == NULL) {
+                       delayed_initializer_t di;
+                       di.initializer = initializer;
+                       di.node_nr     = nr;
+                       ARR_APP1(delayed_initializer_t, env->delayed_initializers, di);
+               }
+               return initializer;
        }
 
        case IR_INITIALIZER_TARVAL:
-               return create_initializer_tarval(read_tv(env));
+               return create_initializer_tarval(read_tarval(env));
 
        case IR_INITIALIZER_NULL:
                return get_initializer_null();
@@ -1308,33 +1729,32 @@ static ir_initializer_t *read_initializer(io_env_t *env)
                }
                return ini;
        }
-
-       default:
-               panic("Unknown initializer kind");
        }
-}
 
+       panic("Unknown initializer kind");
+}
 
 /** Reads a type description and remembers it by its id. */
-static void import_type(io_env_t *env)
+static void read_type(read_env_t *env)
 {
-       int            i;
-       ir_type       *type;
        long           typenr = read_long(env);
        tp_opcode      tpop   = (tp_opcode) read_enum(env, tt_tpo);
        unsigned       size   = (unsigned) read_long(env);
        unsigned       align  = (unsigned) read_long(env);
        ir_type_state  state  = read_type_state(env);
        unsigned       flags  = (unsigned) read_long(env);
+       ir_type       *type;
 
        switch (tpop) {
        case tpo_array: {
-               int ndims = (int) read_long(env);
-               long elemtypenr = read_long(env);
-               ir_type *elemtype = get_type(env, elemtypenr);
-
-               type = new_type_array(ndims, elemtype);
-               for (i = 0; i < ndims; i++) {
+               size_t     n_dimensions = read_size_t(env);
+               ir_type   *elemtype     = read_type_ref(env);
+               size_t     i;
+               ir_entity *element_entity;
+               long       element_entity_nr;
+
+               type = new_type_array(n_dimensions, elemtype);
+               for (i = 0; i < n_dimensions; i++) {
                        char *str = read_word(env);
                        if (strcmp(str, "unknown") != 0) {
                                long lowerbound = atol(str);
@@ -1349,8 +1769,13 @@ static void import_type(io_env_t *env)
                        }
                        obstack_free(&env->obst, str);
                }
+
+               element_entity_nr = read_long(env);
+               element_entity = get_array_element_entity(type);
+               set_id(env, element_entity_nr, element_entity);
+
                set_type_size_bytes(type, size);
-               break;
+               goto finish_type;
        }
 
        case tpo_class: {
@@ -1361,15 +1786,17 @@ static void import_type(io_env_t *env)
                else
                        type = new_type_class(id);
                set_type_size_bytes(type, size);
-               break;
+               goto finish_type;
        }
 
        case tpo_method: {
-               unsigned                  callingconv = (unsigned) read_long(env);
-               mtp_additional_properties addprops    = (mtp_additional_properties) read_long(env);
-               int nparams          = (int)      read_long(env);
-               int nresults         = (int)      read_long(env);
-               int variadicity;
+               unsigned                  callingconv = read_unsigned(env);
+               mtp_additional_properties addprops
+                       = (mtp_additional_properties) read_long(env);
+               size_t nparams  = read_size_t(env);
+               size_t nresults = read_size_t(env);
+               size_t i;
+               int    variadicity;
 
                type = new_type_method(nparams, nresults);
 
@@ -1391,46 +1818,54 @@ static void import_type(io_env_t *env)
 
                set_method_calling_convention(type, callingconv);
                set_method_additional_properties(type, addprops);
-               break;
+               goto finish_type;
        }
 
        case tpo_pointer: {
-               ir_mode *mode     = read_mode(env);
+               ir_mode *mode     = read_mode_ref(env);
                ir_type *pointsto = get_type(env, read_long(env));
                type = new_type_pointer(pointsto);
                set_type_mode(type, mode);
-               break;
+               goto finish_type;
        }
 
        case tpo_primitive: {
-               ir_mode *mode = read_mode(env);
+               ir_mode *mode = read_mode_ref(env);
+               ir_type *base_type = read_type_ref(env);
                type = new_type_primitive(mode);
-               break;
+               if (base_type != firm_none_type) {
+                       set_primitive_base_type(type, base_type);
+               }
+               goto finish_type;
        }
 
        case tpo_struct: {
                ident *id = read_ident_null(env);
                type = new_type_struct(id);
                set_type_size_bytes(type, size);
-               break;
+               goto finish_type;
        }
 
        case tpo_union: {
                ident *id = read_ident_null(env);
                type = new_type_union(id);
                set_type_size_bytes(type, size);
-               break;
+               goto finish_type;
        }
 
+       case tpo_none:
+       case tpo_code:
        case tpo_unknown:
-               return;   /* ignore unknown type */
-
-       default:
-               parse_error(env, "unknown type kind: \"%d\"\n", tpop);
-               skip_to(env, '\n');
+       case tpo_enumeration:
+       case tpo_uninitialized:
+               parse_error(env, "can't import this type kind (%d)", tpop);
                return;
        }
+       parse_error(env, "unknown type kind: \"%d\"\n", tpop);
+       skip_to(env, '\n');
+       return;
 
+finish_type:
        set_type_alignment_bytes(type, align);
        type->flags = flags;
 
@@ -1441,84 +1876,101 @@ static void import_type(io_env_t *env)
 }
 
 /** Reads an entity description and remembers it by its id. */
-static void import_entity(io_env_t *env)
+static void read_entity(read_env_t *env, ir_entity_kind kind)
 {
        long           entnr      = read_long(env);
-       ident         *name       = read_ident(env);
-       ident         *ld_name    = read_ident_null(env);
+       ident         *name       = NULL;
+       ident         *ld_name    = NULL;
        ir_visibility  visibility = ir_visibility_default;
        ir_linkage     linkage    = IR_LINKAGE_DEFAULT;
-       long           typenr;
-       long           ownertypenr;
+       ir_type       *owner      = NULL;
+       ir_entity     *entity     = NULL;
+       int            compiler_generated;
+       ir_volatility  volatility;
        const char    *str;
        ir_type       *type;
-       ir_type       *ownertype;
-       ir_entity     *entity;
 
-       skip_ws(env);
-       while (!isdigit(env->c)) {
-               char     *vstr = read_word(env);
-               unsigned  v;
-
-               skip_ws(env);
+       if (kind != IR_ENTITY_LABEL && kind != IR_ENTITY_PARAMETER) {
+               name    = read_ident(env);
+               ld_name = read_ident_null(env);
+       }
 
-               v = symbol(vstr, tt_visibility);
-               if (v != SYMERROR) {
-                       visibility = (ir_visibility)v;
-                       continue;
+       visibility = read_visibility(env);
+       expect_list_begin(env);
+       while (list_has_next(env)) {
+               linkage |= read_linkage(env);
+       }
+
+       type = read_type_ref(env);
+       if (kind != IR_ENTITY_LABEL)
+               owner = read_type_ref(env);
+
+       compiler_generated = read_long(env) != 0;
+       volatility         = read_volatility(env);
+
+       switch (kind) {
+       case IR_ENTITY_NORMAL:
+               entity = new_entity(owner, name, type);
+               if (ld_name != NULL)
+                       set_entity_ld_ident(entity, ld_name);
+               str = read_word(env);
+               if (strcmp(str, "initializer") == 0) {
+                       ir_initializer_t *initializer = read_initializer(env);
+                       if (initializer != NULL)
+                               set_entity_initializer(entity, initializer);
+               } else if (strcmp(str, "none") == 0) {
+                       /* do nothing */
+               } else {
+                       parse_error(env, "expected 'initializer' or 'none' got '%s'\n", str);
                }
-               v = symbol(vstr, tt_linkage);
-               if (v != SYMERROR) {
-                       linkage |= (ir_linkage)v;
-                       continue;
+               break;
+       case IR_ENTITY_COMPOUND_MEMBER:
+               entity = new_entity(owner, name, type);
+               if (ld_name != NULL)
+                       set_entity_ld_ident(entity, ld_name);
+               set_entity_offset(entity, (int) read_long(env));
+               set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
+               break;
+       case IR_ENTITY_METHOD:
+               entity = new_entity(owner, name, type);
+               if (ld_name != NULL)
+                       set_entity_ld_ident(entity, ld_name);
+               break;
+       case IR_ENTITY_PARAMETER: {
+               char  *str = read_word(env);
+               size_t parameter_number;
+               if (strcmp(str, "va_start") == 0) {
+                       parameter_number = IR_VA_START_PARAMETER_NUMBER;
+               } else {
+                       parameter_number = atol(str);
                }
-               printf("Parser error, expected visibility or linkage, got '%s'\n",
-                      vstr);
+               obstack_free(&env->obst, str);
+               entity = new_parameter_entity(owner, parameter_number, type);
                break;
        }
+       case IR_ENTITY_LABEL: {
+               ir_label_t nr = get_irp_next_label_nr();
+               entity = new_label_entity(nr);
+               break;
+       }
+       }
 
-       typenr      = read_long(env);
-       ownertypenr = read_long(env);
-
-       type      = get_type(env, typenr);
-       ownertype = !ownertypenr ? get_glob_type() : get_type(env, ownertypenr);
-       entity    = new_entity(ownertype, name, type);
-
-       if (ld_name != NULL)
-               set_entity_ld_ident(entity, ld_name);
-       set_entity_offset(entity, (int) read_long(env));
-       set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
-       set_entity_compiler_generated(entity, (int) read_long(env));
-       set_entity_volatility(entity, read_volatility(env));
+       set_entity_compiler_generated(entity, compiler_generated);
+       set_entity_volatility(entity, volatility);
        set_entity_visibility(entity, visibility);
        set_entity_linkage(entity, linkage);
 
-       str = read_word(env);
-       if (strcmp(str, "initializer") == 0) {
-               set_entity_initializer(entity, read_initializer(env));
-       } else if (strcmp(str, "compoundgraph") == 0) {
-               int n = (int) read_long(env);
-               int i;
-               for (i = 0; i < n; i++) {
-                       ir_entity *member = get_entity(env, read_long(env));
-                       ir_node   *irn    = get_node_or_dummy(env, read_long(env));
-                       add_compound_ent_value(entity, irn, member);
-               }
-       } else if (strcmp(str, "none") == 0) {
-               /* do nothing */
-       } else {
-               parse_error(env, "expected 'initializer', 'compoundgraph' or 'none' got '%s'\n", str);
-               exit(1);
+       if (owner != NULL && is_Array_type(owner)) {
+               set_array_element_entity(owner, entity);
        }
 
        set_id(env, entnr, entity);
 }
 
 /** Parses the whole type graph. */
-static int parse_typegraph(io_env_t *env)
+static void read_typegraph(read_env_t *env)
 {
        ir_graph *old_irg = env->irg;
-       keyword_t kwkind;
 
        EXPECT('{');
 
@@ -1526,22 +1978,34 @@ static int parse_typegraph(io_env_t *env)
 
        /* parse all types first */
        while (true) {
+               keyword_t kwkind;
                skip_ws(env);
                if (env->c == '}') {
                        read_c(env);
                        break;
                }
 
-               kwkind = (keyword_t) read_enum(env, tt_keyword);
+               kwkind = read_keyword(env);
                switch (kwkind) {
                case kw_type:
-                       import_type(env);
+                       read_type(env);
                        break;
 
                case kw_entity:
-                       import_entity(env);
+                       read_entity(env, IR_ENTITY_NORMAL);
+                       break;
+               case kw_label:
+                       read_entity(env, IR_ENTITY_LABEL);
+                       break;
+               case kw_method:
+                       read_entity(env, IR_ENTITY_METHOD);
+                       break;
+               case kw_compound_member:
+                       read_entity(env, IR_ENTITY_COMPOUND_MEMBER);
+                       break;
+               case kw_parameter:
+                       read_entity(env, IR_ENTITY_PARAMETER);
                        break;
-
                default:
                        parse_error(env, "type graph element not supported yet: %d\n", kwkind);
                        skip_to(env, '\n');
@@ -1549,35 +2013,67 @@ static int parse_typegraph(io_env_t *env)
                }
        }
        env->irg = old_irg;
-       return 1;
 }
 
-static int read_node_header(io_env_t *env, long *nodenr, ir_node ***preds,
-                            const char **nodename)
+/**
+ * Read a node reference and return the node for it. This assumes that the node
+ * was previously read. This is fine for all normal nodes.
+ * (Note: that we "break" loops by having special code for phi, block or anchor
+ *  nodes in place, firm guarantees us that a loop in the graph always contains
+ *  a phi, block or anchor node)
+ */
+static ir_node *read_node_ref(read_env_t *env)
 {
-       int numpreds;
+       long     nr   = read_long(env);
+       ir_node *node = get_node_or_null(env, nr);
+       if (node == NULL) {
+               parse_error(env, "node %ld not defined (yet?)\n", nr);
+               return new_r_Bad(env->irg, mode_ANY);
+       }
+       return node;
+}
 
-       *nodename = read_word(env);
-       *nodenr   = read_long(env);
+static int read_preds(read_env_t *env)
+{
+       expect_list_begin(env);
+       assert(obstack_object_size(&env->preds_obst) == 0);
+       while (list_has_next(env)) {
+               ir_node *pred = read_node_ref(env);
+               obstack_grow(&env->preds_obst, &pred, sizeof(pred));
+       }
+       return obstack_object_size(&env->preds_obst) / sizeof(ir_node*);
+}
 
-       ARR_RESIZE(ir_node*, *preds, 0);
+static void read_preds_delayed(read_env_t *env, ir_node *node)
+{
+       int             n_preds = 0;
+       delayed_pred_t *d;
 
        expect_list_begin(env);
-       for (numpreds = 0; list_has_next(env); numpreds++) {
-               long     val  = read_long(env);
-               ir_node *pred = get_node_or_dummy(env, val);
-               ARR_APP1(ir_node*, *preds, pred);
+       assert(obstack_object_size(&env->preds_obst) == 0);
+       obstack_blank(&env->preds_obst, sizeof(delayed_pred_t));
+       while (list_has_next(env)) {
+               long pred_nr = read_long(env);
+               obstack_grow(&env->preds_obst, &pred_nr, sizeof(pred_nr));
+               ++n_preds;
        }
+       d          = (delayed_pred_t*) obstack_finish(&env->preds_obst);
+       d->node    = node;
+       d->n_preds = n_preds;
 
-       return numpreds;
+       ARR_APP1(const delayed_pred_t*, env->delayed_preds, d);
 }
 
-static ir_node *read_ASM(io_env_t *env, int numpreds, ir_node **preds)
+static ir_node *read_ASM(read_env_t *env)
 {
-       ir_node *newnode;
+       int                n_in;
+       ir_node          **in;
+       ir_node           *newnode;
        ir_asm_constraint *input_constraints  = NEW_ARR_F(ir_asm_constraint, 0);
        ir_asm_constraint *output_constraints = NEW_ARR_F(ir_asm_constraint, 0);
        ident            **clobbers           = NEW_ARR_F(ident*, 0);
+       ir_node           *block              = read_node_ref(env);
+       op_pin_state       pin_state;
 
        ident *asm_text = read_ident(env);
 
@@ -1586,7 +2082,7 @@ static ir_node *read_ASM(io_env_t *env, int numpreds, ir_node **preds)
                ir_asm_constraint constraint;
                constraint.pos        = read_unsigned(env);
                constraint.constraint = read_ident(env);
-               constraint.mode       = read_mode(env);
+               constraint.mode       = read_mode_ref(env);
                ARR_APP1(ir_asm_constraint, input_constraints, constraint);
        }
 
@@ -1595,7 +2091,7 @@ static ir_node *read_ASM(io_env_t *env, int numpreds, ir_node **preds)
                ir_asm_constraint constraint;
                constraint.pos        = read_unsigned(env);
                constraint.constraint = read_ident(env);
-               constraint.mode       = read_mode(env);
+               constraint.mode       = read_mode_ref(env);
                ARR_APP1(ir_asm_constraint, output_constraints, constraint);
        }
 
@@ -1605,125 +2101,175 @@ static ir_node *read_ASM(io_env_t *env, int numpreds, ir_node **preds)
                ARR_APP1(ident*, clobbers, clobber);
        }
 
-       assert(ARR_LEN(input_constraints) == (size_t)numpreds-1);
+       pin_state = read_pin_state(env);
+
+       n_in = read_preds(env);
+       in   = obstack_finish(&env->preds_obst);
 
-       newnode = new_r_ASM(preds[0], numpreds-1, preds+1,
-                       input_constraints,
-                       ARR_LEN(output_constraints),
-                       output_constraints,
-                       ARR_LEN(clobbers),
-                       clobbers,
-                       asm_text);
+       if (ARR_LEN(input_constraints) != (size_t)n_in) {
+               parse_error(env, "input_constraints != n_in in ir file");
+               return new_r_Bad(env->irg, mode_T);
+       }
+
+       newnode = new_r_ASM(block, n_in, in,
+               input_constraints, ARR_LEN(output_constraints),
+               output_constraints, ARR_LEN(clobbers),
+               clobbers, asm_text);
+       set_irn_pinned(newnode, pin_state);
+       obstack_free(&env->preds_obst, in);
        DEL_ARR_F(clobbers);
        DEL_ARR_F(output_constraints);
        DEL_ARR_F(input_constraints);
        return newnode;
 }
 
-/** Parses an IRG. */
-static int parse_graph(io_env_t *env, ir_graph *irg)
+static ir_node *read_Phi(read_env_t *env)
 {
-       ir_node   **preds = NEW_ARR_F(ir_node*,0);
-       int         i, numpreds, ret = 1;
-       long        nodenr;
-       const char *nodename;
-       ir_node    *node, *newnode;
+       ir_node *block = read_node_ref(env);
+       ir_mode *mode  = read_mode_ref(env);
+       ir_node *res   = new_r_Phi(block, 0, NULL, mode);
+       read_preds_delayed(env, res);
+       return res;
+}
 
-       env->irg = irg;
+static ir_node *read_Block(read_env_t *env)
+{
+       ir_node *res = new_r_Block(env->irg, 0, NULL);
+       read_preds_delayed(env, res);
+       return res;
+}
 
-       EXPECT('{');
+static ir_node *read_labeled_Block(read_env_t *env)
+{
+       ir_node   *res    = new_r_Block(env->irg, 0, NULL);
+       ir_entity *entity = read_entity_ref(env);
+       read_preds_delayed(env, res);
+       set_Block_entity(res, entity);
+       return res;
+}
 
-       while (true) {
-               skip_ws(env);
-               if (env->c == '}') {
-                       read_c(env);
-                       break;
-               }
+static ir_node *read_SymConst(read_env_t *env)
+{
+       ir_mode   *mode   = read_mode_ref(env);
+       ir_entity *entity = read_entity_ref(env);
+       ir_node   *res;
+       symconst_symbol sym;
 
-               numpreds = read_node_header(env, &nodenr, &preds, &nodename);
+       sym.entity_p = entity;
+       res = new_r_SymConst(env->irg, mode, sym, symconst_addr_ent);
+       return res;
+}
 
-               node = get_node_or_null(env, nodenr);
-               newnode = NULL;
+static ir_node *read_Anchor(read_env_t *env)
+{
+       ir_node *res = new_r_Anchor(env->irg);
+       read_preds_delayed(env, res);
+       return res;
+}
 
-               EXPECT('{');
+typedef ir_node* (*read_node_func)(read_env_t *env);
+static pmap *node_readers;
 
-               switch (symbol(nodename, tt_iro)) {
-               case iro_End: {
-                       ir_node *newendblock = preds[0];
-                       newnode = get_irg_end(irg);
-                       exchange(get_nodes_block(newnode), newendblock);
-                       for (i = 1; i < numpreds; i++)
-                               add_irn_n(newnode, preds[i]);
-                       break;
-               }
+static void register_node_reader(ident *ident, read_node_func func)
+{
+       pmap_insert(node_readers, ident, func);
+}
 
-               case iro_Start: {
-                       ir_node *newstartblock = preds[0];
-                       newnode = get_irg_start(irg);
-                       exchange(get_nodes_block(newnode), newstartblock);
-                       break;
-               }
+static ir_node *read_node(read_env_t *env)
+{
+       ident         *id   = read_symbol(env);
+       read_node_func func = pmap_get(node_readers, id);
+       long           nr   = read_long(env);
+       ir_node       *res;
+       if (func == NULL) {
+               parse_error(env, "Unknown nodetype '%s'", get_id_str(id));
+               skip_to(env, '\n');
+               res = new_r_Bad(env->irg, mode_ANY);
+       } else {
+               res = func(env);
+       }
+       set_id(env, nr, res);
+       return res;
+}
 
-               case iro_Block:
-                       newnode = new_r_Block(irg, numpreds, preds);
-                       break;
+static void readers_init(void)
+{
+       assert(node_readers == NULL);
+       node_readers = pmap_create();
+       register_node_reader(new_id_from_str("Anchor"),   read_Anchor);
+       register_node_reader(new_id_from_str("ASM"),      read_ASM);
+       register_node_reader(new_id_from_str("Block"),    read_Block);
+       register_node_reader(new_id_from_str("BlockL"),   read_labeled_Block);
+       register_node_reader(new_id_from_str("Phi"),      read_Phi);
+       register_node_reader(new_id_from_str("SymConst"), read_SymConst);
+       register_generated_node_readers();
+}
 
-               case iro_Anchor:
-                       newnode = irg->anchor;
-                       for (i = 1; i < numpreds; i++)
-                               set_irn_n(newnode, i-1, preds[i]);
-                       set_nodes_block(newnode, preds[0]);
-                       break;
+static void read_graph(read_env_t *env, ir_graph *irg)
+{
+       size_t n_delayed_preds;
+       size_t i;
+       env->irg = irg;
 
-               case iro_SymConst: {
-                       long entnr = read_long(env);
-                       union symconst_symbol sym;
-                       sym.entity_p = get_entity(env, entnr);
-                       ir_mode *mode = read_mode(env);
-                       newnode = new_r_SymConst(irg, mode, sym, symconst_addr_ent);
-                       break;
-               }
+       env->delayed_preds = NEW_ARR_F(const delayed_pred_t*, 0);
 
-               case iro_Proj: {
-                       ir_mode *mode = read_mode(env);
-                       long     pn   = read_long(env);
-                       newnode = new_r_Proj(preds[1], mode, pn);
-                       /* explicitely set block, since preds[1] might be a dummy node
-                        * which is always in the startblock */
-                       set_nodes_block(newnode, preds[0]);
+       EXPECT('{');
+       while (true) {
+               skip_ws(env);
+               if (env->c == '}' || env->c == EOF) {
+                       read_c(env);
                        break;
                }
 
-               case iro_ASM:
-                       newnode = read_ASM(env, numpreds, preds);
-                       break;
-
-               #include "gen_irio_import.inl"
-
-               default:
-                       goto notsupported;
+               read_node(env);
+       }
+
+       /* resolve delayed preds */
+       n_delayed_preds = ARR_LEN(env->delayed_preds);
+       for (i = 0; i < n_delayed_preds; ++i) {
+               const delayed_pred_t *dp  = env->delayed_preds[i];
+               ir_node             **ins = ALLOCAN(ir_node*, dp->n_preds);
+               int                   i;
+               for (i = 0; i < dp->n_preds; ++i) {
+                       long     pred_nr = dp->preds[i];
+                       ir_node *pred    = get_node_or_null(env, pred_nr);
+                       if (pred == NULL) {
+                               parse_error(env, "predecessor %ld of a node not defined\n",
+                                           pred_nr);
+                               goto next_delayed_pred;
+                       }
+                       ins[i] = pred;
                }
-
-               EXPECT('}');
-
-               if (!newnode) {
-notsupported:
-                       parse_error(env, "node type not supported yet: %s\n", nodename);
-                       abort();
+               set_irn_in(dp->node, dp->n_preds, ins);
+               if (is_Anchor(dp->node)) {
+                       irg_anchors a;
+                       for (a = anchor_first; a <= anchor_last; ++a) {
+                               ir_node *old_anchor = get_irg_anchor(irg, a);
+                               ir_node *new_anchor = ins[a];
+                               exchange(old_anchor, new_anchor);
+                       }
                }
-
-               if (node)
-                       exchange(node, newnode);
-               /* Always update hash entry to avoid more uses of id nodes */
-               set_id(env, nodenr, newnode);
+next_delayed_pred: ;
        }
+       DEL_ARR_F(env->delayed_preds);
+       env->delayed_preds = NULL;
+}
 
-       DEL_ARR_F(preds);
-
-       return ret;
+static ir_graph *read_irg(read_env_t *env)
+{
+       ir_entity          *irgent = get_entity(env, read_long(env));
+       ir_graph           *irg    = new_ir_graph(irgent, 0);
+       ir_type            *frame  = read_type_ref(env);
+       irg_inline_property prop   = read_inline_property(env);
+       unsigned            props  = read_unsigned(env);
+       set_irg_frame_type(irg, frame);
+       set_irg_inline_property(irg, prop);
+       set_irg_additional_properties(irg, (mtp_additional_properties)props);
+       read_graph(env, irg);
+       return irg;
 }
 
-static int parse_modes(io_env_t *env)
+static void read_modes(read_env_t *env)
 {
        EXPECT('{');
 
@@ -1731,12 +2277,12 @@ static int parse_modes(io_env_t *env)
                keyword_t kwkind;
 
                skip_ws(env);
-               if (env->c == '}') {
+               if (env->c == '}' || env->c == EOF) {
                        read_c(env);
                        break;
                }
 
-               kwkind = (keyword_t) read_enum(env, tt_keyword);
+               kwkind = read_keyword(env);
                switch (kwkind) {
                case kw_int_mode: {
                        const char *name = read_string(env);
@@ -1753,8 +2299,8 @@ static int parse_modes(io_env_t *env)
                        int size = read_long(env);
                        unsigned modulo_shift = read_long(env);
                        ir_mode *mode = new_reference_mode(name, arith, size, modulo_shift);
-                       set_reference_mode_signed_eq(mode, read_mode(env));
-                       set_reference_mode_unsigned_eq(mode, read_mode(env));
+                       set_reference_mode_signed_eq(mode, read_mode_ref(env));
+                       set_reference_mode_unsigned_eq(mode, read_mode_ref(env));
                        int is_mode_P = read_int(env);
                        if (is_mode_P) {
                                set_modeP_data(mode);
@@ -1776,10 +2322,9 @@ static int parse_modes(io_env_t *env)
                        break;
                }
        }
-       return 1;
 }
 
-static int parse_program(io_env_t *env)
+static void read_program(read_env_t *env)
 {
        EXPECT('{');
 
@@ -1792,58 +2337,67 @@ static int parse_program(io_env_t *env)
                        break;
                }
 
-               kwkind = (keyword_t) read_enum(env, tt_keyword);
+               kwkind = read_keyword(env);
                switch (kwkind) {
                case kw_segment_type: {
                        ir_segment_t  segment = (ir_segment_t) read_enum(env, tt_segment);
-                       ir_type      *type    = read_type(env);
+                       ir_type      *type    = read_type_ref(env);
                        set_segment_type(segment, type);
                        break;
                }
+               case kw_asm: {
+                       ident *text = read_ident(env);
+                       add_irp_asm(text);
+                       break;
+               }
                default:
                        parse_error(env, "unexpected keyword %d\n", kwkind);
                        skip_to(env, '\n');
                }
        }
-       return 1;
 }
 
-void ir_import(const char *filename)
+int ir_import(const char *filename)
 {
        FILE *file = fopen(filename, "rt");
+       int   res;
        if (file == NULL) {
                perror(filename);
-               exit(1);
+               return 1;
        }
 
-       ir_import_file(file, filename);
-
+       res = ir_import_file(file, filename);
        fclose(file);
+
+       return res;
 }
 
-void ir_import_file(FILE *input, const char *inputname)
+int ir_import_file(FILE *input, const char *inputname)
 {
-       int oldoptimize = get_optimize();
-       firm_verification_t oldver = get_node_verification_mode();
-       io_env_t ioenv;
-       io_env_t *env = &ioenv;
-       size_t i, n;
+       read_env_t          myenv;
+       int                 oldoptimize = get_optimize();
+       read_env_t         *env         = &myenv;
+       size_t              i;
+       size_t              n;
+       size_t              n_delayed_initializers;
 
+       readers_init();
        symtbl_init();
 
        memset(env, 0, sizeof(*env));
        obstack_init(&env->obst);
+       obstack_init(&env->preds_obst);
        env->idset      = new_set(id_cmp, 128);
        env->fixedtypes = NEW_ARR_F(ir_type *, 0);
        env->inputname  = inputname;
        env->file       = input;
        env->line       = 1;
+       env->delayed_initializers = NEW_ARR_F(delayed_initializer_t, 0);
 
        /* read first character */
        read_c(env);
 
        set_optimize(0);
-       do_node_verification(FIRM_VERIFICATION_OFF);
 
        while (true) {
                keyword_t kw;
@@ -1852,35 +2406,30 @@ void ir_import_file(FILE *input, const char *inputname)
                if (env->c == EOF)
                        break;
 
-               kw = (keyword_t)read_enum(env, tt_keyword);
+               kw = read_keyword(env);
                switch (kw) {
                case kw_modes:
-                       if (!parse_modes(env)) goto end;
+                       read_modes(env);
                        break;
 
                case kw_typegraph:
-                       if (!parse_typegraph(env)) goto end;
+                       read_typegraph(env);
                        break;
 
                case kw_irg:
-               {
-                       ir_entity *irgent = get_entity(env, read_long(env));
-                       ir_graph *irg = new_ir_graph(irgent, 0);
-                       set_irg_frame_type(irg, get_type(env, read_long(env)));
-                       if (!parse_graph(env, irg)) goto end;
+                       read_irg(env);
                        break;
-               }
 
                case kw_constirg: {
                        ir_graph *constirg = get_const_code_irg();
                        long bodyblockid = read_long(env);
                        set_id(env, bodyblockid, constirg->current_block);
-                       if (!parse_graph(env, constirg)) goto end;
+                       read_graph(env, constirg);
                        break;
                }
 
                case kw_program:
-                       parse_program(env);
+                       read_program(env);
                        break;
 
                default: {
@@ -1890,19 +2439,41 @@ void ir_import_file(FILE *input, const char *inputname)
                }
        }
 
-end:
        n = ARR_LEN(env->fixedtypes);
        for (i = 0; i < n; i++)
                set_type_state(env->fixedtypes[i], layout_fixed);
 
        DEL_ARR_F(env->fixedtypes);
 
+       /* resolve delayed initializers */
+       n_delayed_initializers = ARR_LEN(env->delayed_initializers);
+       for (i = 0; i < n_delayed_initializers; ++i) {
+               const delayed_initializer_t *di   = &env->delayed_initializers[i];
+               ir_node                     *node = get_node_or_null(env, di->node_nr);
+               if (node == NULL) {
+                       parse_error(env, "node %ld mentioned in an initializer was never defined\n",
+                                   di->node_nr);
+                       continue;
+               }
+               assert(di->initializer->kind == IR_INITIALIZER_CONST);
+               di->initializer->consti.value = node;
+       }
+       DEL_ARR_F(env->delayed_initializers);
+       env->delayed_initializers = NULL;
+
        del_set(env->idset);
 
        irp_finalize_cons();
 
-       do_node_verification(oldver);
        set_optimize(oldoptimize);
 
+       obstack_free(&env->preds_obst, NULL);
        obstack_free(&env->obst, NULL);
+
+       pmap_destroy(node_readers);
+       node_readers = NULL;
+
+       return env->read_errors;
 }
+
+#include "gen_irio.inl"
index 441162c..959f7f4 100644 (file)
@@ -46,20 +46,6 @@ static struct obstack modes;
 /** The list of all currently existing modes. */
 static ir_mode **mode_list;
 
-const char *get_mode_arithmetic_name(ir_mode_arithmetic ari)
-{
-#define X(a)    case a: return #a
-       switch (ari) {
-               X(irma_uninitialized);
-               X(irma_none);
-               X(irma_twos_complement);
-               X(irma_ieee754);
-               X(irma_x86_extended_float);
-               default: return "<unknown>";
-       }
-#undef X
-}
-
 static bool modes_are_equal(const ir_mode *m, const ir_mode *n)
 {
        return m->sort         == n->sort &&
index 2fab4b0..5c86c84 100755 (executable)
@@ -17,18 +17,13 @@ def warning(msg):
 def format_args(arglist):
        return "\n".join(arglist)
 
-def format_ifnset(string, node, key):
-       if hasattr(node, key):
-               return ""
-       return string
-
 def format_block(node):
        if hasattr(node, "knownBlock"):
                if hasattr(node, "knownGraph"):
                        return ""
-               return "irg"
+               return "env->irg"
        else:
-               return "preds[0]"
+               return "block"
 
 def format_arguments(string):
        args = re.split('\s*\n\s*', string)
@@ -38,152 +33,245 @@ def format_arguments(string):
                args = args[:-1]
        return ", ".join(args)
 
+def filter_isnot(list, flag):
+       return filter(lambda x: not hasattr(x, flag), list)
+
+def filter_notset(list, flag):
+       return filter(lambda x: not getattr(x,flag), list)
+
+def filter_hasnot(list, flag):
+       return filter(lambda x: flag not in x, list)
+
 env = Environment()
 env.filters['args']      = format_args
-env.filters['ifnset']    = format_ifnset
 env.filters['block']     = format_block
 env.filters['arguments'] = format_arguments
+env.filters['isnot']     = filter_isnot
+env.filters['notset']    = filter_notset
+env.filters['hasnot']    = filter_hasnot
 
 def get_io_type(type, attrname, node):
        if type == "ir_tarval*":
-               importcmd = "ir_tarval *%s = read_tv(env);" % attrname
-               exportcmd = "write_tarval(env, %(val)s);";
+               importcmd = "read_tarval(env)"
+               exportcmd = "write_tarval(env, %(val)s);"
        elif type == "ir_mode*":
-               importcmd = "ir_mode *%s = read_mode(env);" % attrname
-               exportcmd = "write_mode(env, %(val)s);"
+               importcmd = "read_mode_ref(env)"
+               exportcmd = "write_mode_ref(env, %(val)s);"
        elif type == "ir_entity*":
-               importcmd = "ir_entity *%s = read_entity(env);" % attrname
+               importcmd = "read_entity_ref(env)"
                exportcmd = "write_entity_ref(env, %(val)s);"
        elif type == "ir_type*":
-               importcmd = "ir_type *%s = read_type(env);" % attrname
+               importcmd = "read_type_ref(env)"
                exportcmd = "write_type_ref(env, %(val)s);"
-       elif type == "long" and node.name == "Proj":
-               importcmd = "long %s = read_long(env);" % attrname
+       elif type == "long":
+               importcmd = "read_long(env)"
                exportcmd = "write_long(env, %(val)s);"
-       elif type == "ir_relation" or type == "ir_where_alloc":
-               importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
-               exportcmd = "write_long(env, (long) %(val)s);"
+       elif type == "ir_relation":
+               importcmd = "read_relation(env)"
+               exportcmd = "write_relation(env, %(val)s);"
+       elif type == "ir_where_alloc":
+               importcmd = "read_where_alloc(env)"
+               exportcmd = "write_where_alloc(env, %(val)s);"
        elif type == "ir_align":
-               importcmd = "ir_align %s = read_align(env);" % attrname
+               importcmd = "read_align(env)"
                exportcmd = "write_align(env, %(val)s);"
        elif type == "ir_volatility":
-               importcmd = "ir_volatility %s = read_volatility(env);" % attrname
+               importcmd = "read_volatility(env)"
                exportcmd = "write_volatility(env, %(val)s);"
        elif type == "ir_cons_flags":
-               importcmd = "ir_cons_flags %s = cons_none;" % attrname
+               importcmd = "cons_none"
                exportcmd = "" # can't really export cons_flags
        elif type == "op_pin_state":
-               importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
-               exportcmd = "write_pin_state(env, irn);"
+               importcmd = "read_pin_state(env)"
+               exportcmd = "write_pin_state(env, node);"
        elif type == "ir_builtin_kind":
-               importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
-               exportcmd = "write_builtin_kind(env, irn);"
+               importcmd = "read_builtin_kind(env)"
+               exportcmd = "write_builtin_kind(env, node);"
        elif type == "cond_kind":
-               importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
-               exportcmd = "write_cond_kind(env, irn);"
+               importcmd = "read_cond_kind(env)"
+               exportcmd = "write_cond_kind(env, node);"
        elif type == "cond_jmp_predicate":
-               importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
-               exportcmd = "write_cond_jmp_predicate(env, irn);"
+               importcmd = "read_cond_jmp_predicate(env)"
+               exportcmd = "write_cond_jmp_predicate(env, node);"
        elif type == "int":
-               importcmd = "int %s = read_int(env);" % attrname
+               importcmd = "read_int(env)"
                exportcmd = "write_int(env, %(val)s);"
        elif type == "unsigned":
-               importcmd = "unsigned %s = read_unsigned(env);" % attrname
+               importcmd = "read_unsigned(env)"
                exportcmd = "write_unsigned(env, %(val)s);"
        elif type == "long":
-               importcmd = "long %s = read_long(env);" % attrname
+               importcmd = "read_long(env)"
                exportcmd = "write_long(env, %(val)s);"
+       elif type == "ir_switch_table*":
+               importcmd = "read_switch_table(env)"
+               exportcmd = "write_switch_table(env, %(val)s);"
        else:
                warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
-               importcmd = """// BAD: %s %s
-                       %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
+               importcmd = "/* BAD: %s %s */ (%s)0" % (type, attrname, type)
                exportcmd = "// BAD: %s" % type
        return (importcmd, exportcmd)
 
 def prepare_attr(node, attr):
        (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
        attr["importcmd"] = importcmd
-       attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (node.name, attr["name"])}
+       attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(node)" % (node.name, attr["name"])}
 
 
 def preprocess_node(node):
-       # dynamic pin state means, we have to im/export that
-       if is_dynamic_pinned(node):
-               newattr = dict(
-                       name = "state",
-                       type = "op_pin_state"
-               )
-               if hasattr(node, "pinned_init"):
-                       newattr["init"] = node.pinned_init
-               node.attrs.append(newattr)
-
        verify_node(node)
 
+       if node.customSerializer:
+               return
+
        # construct node arguments
        arguments = [ ]
-       initargs = [ ]
-       i = 1
+       extraattrs = [ ]
        for input in node.ins:
-               arguments.append("preds[%i]" % i)
-               i += 1
+               arguments.append("in_%s" % input[0])
 
        if node.arity == "variable" or node.arity == "dynamic":
-               arguments.append("numpreds - %i" % i)
-               arguments.append("preds + %i" % i)
+               arguments.append("n_preds")
+               arguments.append("preds")
 
        if not hasattr(node, "mode"):
                arguments.append("mode")
 
        for attr in node.attrs:
                prepare_attr(node, attr)
-               if "init" in attr:
-                       if attr["type"] == "op_pin_state":
-                               initfunc = "set_irn_pinned"
-                       else:
-                               initfunc = "set_" + node.name + "_" + attr["name"]
-                       initargs.append((attr["name"], initfunc))
+               if "to_flags" in attr:
+                       node.constructorFlags = True
+                       attr['to_flags'] = attr['to_flags'] % (attr["name"])
+               elif "init" in attr:
+                       extraattrs.append(attr)
                else:
                        arguments.append(attr["name"])
 
        for arg in node.constructor_args:
-               prepare_attr(node, arg)
-               arguments.append(arg["name"])
-
-       node.arguments = arguments
-       node.initargs = initargs
-
-export_attrs_template = env.from_string('''
-       case iro_{{node.name}}:
-               {{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
-               {% for attr in node.attrs %}{{attr.exportcmd}}
-               {% endfor %}
-               {% for attr in node.constructor_args %}{{attr.exportcmd}}
-               {% endfor %}break;''')
-
-import_attrs_template = env.from_string('''
-       case iro_{{node.name}}: {
-               {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
-               {% for attr in node.attrs %}
-               {{attr.importcmd}}
-               {% endfor -%}
-               {% for attr in node.constructor_args %}
-               {{attr.importcmd}}
-               {% endfor -%}
-               newnode = new_r_{{node.name}}(
-{%- filter arguments %}
+               if arg['type'] != "ir_cons_flags" and arg['name'] != "flags":
+                       error("only ir_cons_flags constructor arg supported in irio")
+                       continue
+               node.constructorFlags = True
+               arguments.append("flags")
+
+       node.arguments  = arguments
+       node.extraattrs = extraattrs
+       node.dynamic_pinned = is_dynamic_pinned(node)
+
+io_template = env.from_string('''/* Warning: automatically generated code */
+{%- for node in nodes|notset('customSerializer') %}
+static ir_node *read_{{node.name}}(read_env_t *env)
+{
+       {%- if not node.knownBlock %}
+       ir_node *block = read_node_ref(env);
+       {%- endif %}
+       {%- for input in node.ins %}
+       ir_node *in_{{input[0]}} = read_node_ref(env);
+       {%- endfor %}
+       {%- if not hasattr(node, "mode") %}
+       ir_mode *mode = read_mode_ref(env);
+       {%- endif %}
+       {%- for attr in node.attrs %}
+       {{attr.type}} {{attr.name}} = {{attr.importcmd}};
+       {%- endfor %}
+       {%- if node.dynamic_pinned %}
+       op_pin_state pin_state = read_pin_state(env);
+       {%- endif %}
+       {%- if "fragile" in node.flags %}
+       bool throws = read_throws(env);
+       {%- endif %}
+       {%- if node.arity == "dynamic" or node.arity == "variable" %}
+       int       n_preds = read_preds(env);
+       ir_node **preds   = obstack_finish(&env->preds_obst);
+       {%- endif %}
+       {%- if node.constructorFlags %}
+       ir_cons_flags flags = cons_none;
+       {%- endif %}
+       ir_node *res;
+       {%- if node.constructorFlags %}
+               {%- for attr in node.attrs %}
+                       {%- if "to_flags" in attr %}
+       flags |= {{attr.to_flags}};
+                       {%- endif %}
+               {%- endfor %}
+               {%- if node.dynamic_pinned %}
+       flags |= pin_state == op_pin_state_floats ? cons_floats : 0;
+               {%- endif %}
+               {%- if "fragile" in node.flags %}
+       flags |= throws ? cons_throws_exception : 0;
+               {%- endif %}
+       {%- endif %}
+       res = new_r_{{node.name}}(
+               {%- filter arguments %}
 {{node|block}}
 {{node.arguments|args}}
+               {%- if node.dynamic_pinned and not hasattr(node, "pinned_init") %}
+pin_state
+               {%- endif %}
 {% endfilter %});
-               {% for (initarg, initfunc) in node.initargs %}
-               {{initfunc}}(newnode, {{initarg}});
-               {% endfor -%}
-               break;
-       }
+
+       {%- if node.arity == "dynamic" or node.arity == "variable" %}
+       obstack_free(&env->preds_obst, preds);
+       {%- endif %}
+       {%- for attr in node.extraattrs %}
+       set_{{node.name}}_{{attr.name}}(res, {{attr.name}});
+       {%- endfor %}
+       {%- if not node.constructorFlags %}
+               {%- if node.dynamic_pinned and hasattr(node, "pinned_init") %}
+       set_irn_pinned(res, pin_state);
+               {%- endif %}
+               {%- if "fragile" in node.flags and hasattr(node, "throws_init") %}
+       ir_set_throws_exception(res, throws);
+               {%- endif %}
+       {%- endif %}
+       return res;
+}
+{% endfor %}
+
+{%- for node in nodes|notset('customSerializer') %}
+static void write_{{node.name}}(write_env_t *env, const ir_node *node)
+{
+       write_symbol(env, "{{node.name}}");
+       write_node_nr(env, node);
+       {%- if not node.knownBlock %}
+       write_node_ref(env, get_nodes_block(node));
+       {%- endif %}
+       {%- for input in node.ins %}
+       write_node_ref(env, get_{{node.name}}_{{input[0]}}(node));
+       {%- endfor %}
+       {%- if not hasattr(node, "mode") %}
+       write_mode_ref(env, get_irn_mode(node));
+       {%- endif %}
+       {%- for attr in node.attrs %}
+       {{attr.exportcmd}}
+       {%- endfor %}
+       {%- if node.dynamic_pinned %}
+       write_pin_state(env, get_irn_pinned(node));
+       {%- endif %}
+       {%- if "fragile" in node.flags %}
+       write_throws(env, ir_throws_exception(node));
+       {%- endif %}
+       {%- if node.arity == "dynamic" or node.arity == "variable" %}
+       write_pred_refs(env, node, {% if node.ins %}n_{{node.name}}_max+1{% else %}0{%endif%});
+       {%- endif %}
+}
+{% endfor %}
+
+static void register_generated_node_readers(void)
+{
+       {%- for node in nodes|notset('customSerializer') %}
+       register_node_reader(new_id_from_str("{{node.name}}"), read_{{node.name}});
+       {%- endfor %}
+}
+
+static void register_generated_node_writers(void)
+{
+       {%- for node in nodes|notset('customSerializer') %}
+       register_node_writer(op_{{node.name}}, write_{{node.name}});
+       {%- endfor %}
+}
 ''')
 
 def main(argv):
-       """the main function"""
-
        if len(argv) < 3:
                print "usage: %s specname(ignored) destdirectory" % argv[0]
                sys.exit(1)
@@ -194,32 +282,11 @@ def main(argv):
        for node in ir_spec.nodes:
                if isAbstract(node):
                        continue
-               real_nodes.append(node)
-
-       file = open(gendir + "/gen_irio_export.inl", "w");
-       file.write("/* Warning: automatically generated code */")
-       for node in real_nodes:
-               if node.customSerializer:
-                       continue
-
                preprocess_node(node)
-               file.write(export_attrs_template.render(vars()))
-       file.write("\n")
-       file.close()
-
-       file = open(gendir + "/gen_irio_import.inl", "w");
-       file.write("/* Warning: automatically generated code */")
-       for node in real_nodes:
-               if node.customSerializer:
-                       continue
-               file.write(import_attrs_template.render(vars()))
-       file.write("\n")
-       file.close()
+               real_nodes.append(node)
 
-       file = open(gendir + "/gen_irio_lex.inl", "w");
-       file.write("/* Warning: automatically generated code */")
-       for node in real_nodes:
-               file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
+       file = open(gendir + "/gen_irio.inl", "w");
+       file.write(io_template.render(nodes = real_nodes, hasattr=hasattr))
        file.close()
 
 main(sys.argv)
index 06fb922..facddd8 100755 (executable)
@@ -164,7 +164,7 @@ class Deleted(Op):
        flags            = [ ]
        pinned           = "yes"
        noconstructor    = True
-       customSerializer = True
+       customSerializer = True # this has no serializer
 
 class Block(Op):
        """A basic block"""
@@ -498,7 +498,6 @@ class End(Op):
        knownBlock       = True
        block            = "get_irg_end_block(irg)"
        singleton        = True
-       customSerializer = True
 
 class Eor(Binop):
        """returns the result of a bitwise exclusive or operation of its operands"""
@@ -603,12 +602,14 @@ class Load(Op):
                        name      = "volatility",
                        comment   = "volatile loads are a visible side-effect and may not be optimized",
                        init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
+                       to_flags  = "%s == volatility_is_volatile ? cons_volatile : 0"
                ),
                dict(
                        type      = "ir_align",
                        name      = "unaligned",
                        comment   = "pointers to unaligned loads don't need to respect the load-mode/type alignments",
                        init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
+                       to_flags  = "%s == align_non_aligned ? cons_unaligned : 0"
                ),
        ]
        attr_struct = "load_attr"
@@ -715,6 +716,7 @@ class Phi(Op):
           As we can't distinguish these easily we keep all of them alive. */
        if (is_Phi(res) && mode == mode_M)
                add_End_keepalive(get_irg_end(irg), res);'''
+       customSerializer = True
 
 class Pin(Op):
        """Pin the value of the node node in the current block. No users of the Pin
@@ -738,7 +740,6 @@ class Proj(Op):
        knownGraph       = True
        block            = "get_nodes_block(irn_pred)"
        graph            = "get_irn_irg(irn_pred)"
-       customSerializer = True
        attrs      = [
                dict(
                        type    = "long",
@@ -828,7 +829,6 @@ class Start(Op):
        flags            = [ "cfopcode" ]
        singleton        = True
        knownBlock       = True
-       customSerializer = True
        block            = "get_irg_start_block(irg)"
 
 class Store(Op):
@@ -854,12 +854,14 @@ class Store(Op):
                        name      = "volatility",
                        comment   = "volatile stores are a visible side-effect and may not be optimized",
                        init      = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
+                       to_flags  = "%s == volatility_is_volatile ? cons_volatile : 0"
                ),
                dict(
                        type      = "ir_align",
                        name      = "unaligned",
                        comment   = "pointers to unaligned stores don't need to respect the load-mode/type alignments",
                        init      = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
+                       to_flags  = "%s == align_non_aligned ? cons_unaligned : 0"
                ),
        ]
        constructor_args = [