From: Matthias Braun Date: Wed, 16 Nov 2011 18:53:52 +0000 (+0100) Subject: irio: complete rewrite X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=bd092bd1f52df17d8317a2e16b9e9e2dc9b8bed6;p=libfirm irio: complete rewrite This should fix all known bugs, make the code easier to read and more robust. --- diff --git a/include/libfirm/irio.h b/include/libfirm/irio.h index 0a9e2c66e..a188072af 100644 --- a/include/libfirm/irio.h +++ b/include/libfirm/irio.h @@ -35,43 +35,32 @@ /** * 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" diff --git a/include/libfirm/irmode.h b/include/libfirm/irmode.h index 404c67a18..cb26acafc 100644 --- a/include/libfirm/irmode.h +++ b/include/libfirm/irmode.h @@ -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. * diff --git a/ir/ir/irio.c b/ir/ir/irio.c index e89753318..387bac614 100644 --- a/ir/ir/irio.c +++ b/ir/ir/irio.c @@ -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" @@ -43,67 +43,94 @@ #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 ""; } @@ -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" diff --git a/ir/ir/irmode.c b/ir/ir/irmode.c index 441162cbc..959f7f467 100644 --- a/ir/ir/irmode.c +++ b/ir/ir/irmode.c @@ -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 ""; - } -#undef X -} - static bool modes_are_equal(const ir_mode *m, const ir_mode *n) { return m->sort == n->sort && diff --git a/scripts/gen_ir_io.py b/scripts/gen_ir_io.py index 2fab4b015..5c86c8444 100755 --- a/scripts/gen_ir_io.py +++ b/scripts/gen_ir_io.py @@ -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) diff --git a/scripts/ir_spec.py b/scripts/ir_spec.py index 06fb922ea..facddd8d9 100755 --- a/scripts/ir_spec.py +++ b/scripts/ir_spec.py @@ -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 = [