/*
- * Copyright (C) 1995-2009 University of Karlsruhe. All right reserved.
+ * Copyright (C) 1995-2011 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
/**
* @file
* @brief Write textual representation of firm to file.
- * @author Moritz Kroll
- * @version $Id$
+ * @author Moritz Kroll, Matthias Braun
*/
#include "config.h"
#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdarg.h>
#include "irio.h"
#include "irnode_t.h"
#include "irprog.h"
#include "irgraph_t.h"
-#include "ircons.h"
+#include "irprintf.h"
+#include "ircons_t.h"
#include "irgmod.h"
#include "irflag_t.h"
#include "irgwalk.h"
#include "tv.h"
#include "array.h"
#include "error.h"
-#include "adt/set.h"
+#include "typerep.h"
+#include "set.h"
+#include "obst.h"
+#include "pmap.h"
+#include "pdeq.h"
#define SYMERROR ((unsigned) ~0)
-typedef struct io_env_t
-{
+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;
+ struct obstack preds_obst;
+ delayed_initializer_t *delayed_initializers;
+ const delayed_pred_t **delayed_preds;
+} read_env_t;
+
+typedef struct write_env_t {
FILE *file;
- set *idset; /**< id_entry set, which maps from file ids to new Firm elements */
- int ignoreblocks;
- int line, col;
- ir_type **fixedtypes;
-} io_env_t;
-
-typedef struct lex_state_t
-{
- long offs;
- int line, col;
-} lex_state_t;
+ pdeq *write_queue;
+} write_env_t;
-typedef enum typetag_t
-{
+typedef enum typetag_t {
tt_align,
- tt_allocation,
- tt_builtin,
- tt_cond_kind,
+ tt_builtin_kind,
tt_cond_jmp_predicate,
tt_initializer,
- tt_iro,
tt_keyword,
+ tt_linkage,
tt_mode_arithmetic,
- tt_peculiarity,
tt_pin_state,
+ tt_segment,
+ tt_throws,
tt_tpo,
tt_type_state,
- tt_variability,
tt_visibility,
- tt_volatility
+ tt_volatility,
+ tt_where_alloc,
} typetag_t;
-typedef enum keyword_t
-{
+typedef enum keyword_t {
+ kw_asm,
+ kw_compound_member,
kw_constirg,
kw_entity,
- kw_frametype,
+ kw_float_mode,
+ kw_int_mode,
kw_irg,
- kw_mode,
+ kw_label,
+ kw_method,
kw_modes,
- kw_valuetype,
+ kw_parameter,
+ kw_program,
+ kw_reference_mode,
+ kw_segment_type,
kw_type,
- kw_typegraph
+ kw_typegraph,
+ kw_unknown,
} 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;
/** The symbol table, a set of symbol_t elements. */
static set *symtbl;
-
-/**
- * Calculate a hash value for a string.
- */
-static unsigned string_hash(const char *str, int len)
-{
- return str[0] * 27893 ^ str[len-1] * 81 ^ str[len >> 1];
-}
-
/**
* Compare two symbol table entries.
*/
const symbol_t *keyentry = (const symbol_t *) key;
(void) size;
res = entry->typetag - keyentry->typetag;
- if(res) return res;
+ if (res) return res;
return strcmp(entry->str, keyentry->str);
}
return entry->id - keyentry->id;
}
+static void __attribute__((format(printf, 2, 3)))
+parse_error(read_env_t *env, const char *fmt, ...)
+{
+ va_list ap;
+ unsigned line = env->line;
+
+ /* workaround read_c "feature" that a '\n' triggers the line++
+ * instead of the character after the '\n' */
+ if (env->c == '\n') {
+ 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(FIRM_VERIFICATION_OFF);
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
/** Initializes the symbol table. May be called more than once without problems. */
static void symtbl_init(void)
{
symbol_t key;
/* Only initialize once */
- if(symtbl != NULL)
+ if (symtbl != NULL)
return;
symtbl = new_set(symbol_cmp, 256);
-#define INSERT(s, tt, cod) \
+#define INSERT(tt, s, cod) \
key.str = (s); \
key.typetag = (tt); \
key.code = (cod); \
- set_insert(symtbl, &key, sizeof(key), string_hash(s, sizeof(s)-1) + tt * 17)
-
-#define INSERTENUM(tt, e) INSERT(#e, tt, e)
-#define INSERTKEYWORD(k) INSERT(#k, tt_keyword, kw_##k)
-
- INSERT("array", tt_tpo, tpo_array);
- INSERT("class", tt_tpo, tpo_class);
- INSERT("method", tt_tpo, tpo_method);
- INSERT("pointer", tt_tpo, tpo_pointer);
- INSERT("primitive", tt_tpo, tpo_primitive);
- INSERT("struct", tt_tpo, tpo_struct);
- INSERT("union", tt_tpo, tpo_union);
- INSERT("Unknown", tt_tpo, tpo_unknown);
-
+ (void)set_insert(symbol_t, symtbl, &key, sizeof(key), hash_str(s) + tt * 17)
+
+#define INSERTENUM(tt, e) INSERT(tt, #e, e)
+#define INSERTKEYWORD(k) INSERT(tt_keyword, #k, kw_##k)
+
+ INSERT(tt_tpo, "array", tpo_array);
+ INSERT(tt_tpo, "class", tpo_class);
+ INSERT(tt_tpo, "method", tpo_method);
+ INSERT(tt_tpo, "pointer", tpo_pointer);
+ INSERT(tt_tpo, "primitive", tpo_primitive);
+ INSERT(tt_tpo, "struct", tpo_struct);
+ INSERT(tt_tpo, "union", tpo_union);
+ INSERT(tt_tpo, "Unknown", tpo_unknown);
+
+ INSERT(tt_segment, "global", IR_SEGMENT_GLOBAL);
+ INSERT(tt_segment, "thread_local", IR_SEGMENT_THREAD_LOCAL);
+ INSERT(tt_segment, "constructors", IR_SEGMENT_CONSTRUCTORS);
+ INSERT(tt_segment, "destructors", IR_SEGMENT_DESTRUCTORS);
+
+ INSERT(tt_linkage, "constant", IR_LINKAGE_CONSTANT);
+ INSERT(tt_linkage, "weak", IR_LINKAGE_WEAK);
+ INSERT(tt_linkage, "garbage_collect", IR_LINKAGE_GARBAGE_COLLECT);
+ INSERT(tt_linkage, "merge", IR_LINKAGE_MERGE);
+ INSERT(tt_linkage, "hidden_user", IR_LINKAGE_HIDDEN_USER);
+
+ INSERT(tt_visibility, "local", ir_visibility_local);
+ INSERT(tt_visibility, "external", ir_visibility_external);
+ 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(frametype);
+ INSERTKEYWORD(float_mode);
+ INSERTKEYWORD(int_mode);
INSERTKEYWORD(irg);
- INSERTKEYWORD(mode);
+ INSERTKEYWORD(label);
+ INSERTKEYWORD(method);
INSERTKEYWORD(modes);
- INSERTKEYWORD(valuetype);
+ INSERTKEYWORD(parameter);
+ INSERTKEYWORD(program);
+ INSERTKEYWORD(reference_mode);
+ INSERTKEYWORD(segment_type);
INSERTKEYWORD(type);
INSERTKEYWORD(typegraph);
-
-#include "gen_irio_lex.inl"
+ INSERTKEYWORD(unknown);
INSERTENUM(tt_align, align_non_aligned);
INSERTENUM(tt_align, align_is_aligned);
- INSERTENUM(tt_allocation, allocation_automatic);
- INSERTENUM(tt_allocation, allocation_parameter);
- INSERTENUM(tt_allocation, allocation_dynamic);
- INSERTENUM(tt_allocation, allocation_static);
-
- 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_addess);
- 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_cond_kind, dense);
- INSERTENUM(tt_cond_kind, fragmentary);
+ 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);
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_ones_complement);
- INSERTENUM(tt_mode_arithmetic, irma_int_BCD);
- INSERTENUM(tt_mode_arithmetic, irma_ieee754);
- INSERTENUM(tt_mode_arithmetic, irma_float_BCD);
-
- INSERTENUM(tt_peculiarity, peculiarity_description);
- INSERTENUM(tt_peculiarity, peculiarity_inherited);
- INSERTENUM(tt_peculiarity, peculiarity_existent);
+ 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);
INSERTENUM(tt_pin_state, op_pin_state_floats);
INSERTENUM(tt_pin_state, op_pin_state_pinned);
INSERTENUM(tt_type_state, layout_undefined);
INSERTENUM(tt_type_state, layout_fixed);
- INSERTENUM(tt_variability, variability_uninitialized);
- INSERTENUM(tt_variability, variability_initialized);
- INSERTENUM(tt_variability, variability_part_constant);
- INSERTENUM(tt_variability, variability_constant);
-
- INSERTENUM(tt_visibility, visibility_local);
- INSERTENUM(tt_visibility, visibility_external_visible);
- INSERTENUM(tt_visibility, visibility_external_allocated);
-
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
}
+static const char *get_segment_name(ir_segment_t segment)
+{
+ switch (segment) {
+ case IR_SEGMENT_GLOBAL: return "global";
+ case IR_SEGMENT_THREAD_LOCAL: return "thread_local";
+ case IR_SEGMENT_CONSTRUCTORS: return "constructors";
+ case IR_SEGMENT_DESTRUCTORS: return "destructors";
+ }
+ panic("INVALID_SEGMENT");
+}
+
+static const char *get_visibility_name(ir_visibility visibility)
+{
+ switch (visibility) {
+ case ir_visibility_local: return "local";
+ case ir_visibility_external: return "external";
+ case ir_visibility_private: return "private";
+ }
+ panic("INVALID_VISIBILITY");
+}
+
+static const char *get_mode_arithmetic_name(ir_mode_arithmetic arithmetic)
+{
+ switch (arithmetic) {
+ case irma_none: return "none";
+ case irma_twos_complement: return "twos_complement";
+ case irma_ieee754: return "ieee754";
+ case irma_x86_extended_float: return "x86_extended_float";
+ }
+ panic("invalid mode_arithmetic");
+}
+
/** Returns the according symbol value for the given string and tag, or SYMERROR if none was found. */
static unsigned symbol(const char *str, typetag_t typetag)
{
key.str = str;
key.typetag = typetag;
- entry = set_find(symtbl, &key, sizeof(key), string_hash(str, strlen(str)) + typetag * 17);
+ entry = set_find(symbol_t, symtbl, &key, sizeof(key), hash_str(str) + typetag * 17);
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;
+ fprintf(env->file, "%ld ", value);
+}
- entry = set_find(env->idset, &key, sizeof(key), (unsigned) id);
- return entry ? entry->elem : NULL;
+static void write_int(write_env_t *env, int value)
+{
+ fprintf(env->file, "%d ", value);
}
-static void set_id(io_env_t *env, long id, void *elem)
+static void write_unsigned(write_env_t *env, unsigned value)
{
- id_entry key;
- key.id = id;
- key.elem = elem;
- set_insert(env->idset, &key, sizeof(key), (unsigned) id);
+ fprintf(env->file, "%u ", value);
+}
+
+static void write_size_t(write_env_t *env, size_t value)
+{
+ ir_fprintf(env->file, "%zu ", value);
}
-static void write_mode(io_env_t *env, ir_mode *mode)
+static void write_symbol(write_env_t *env, const char *symbol)
{
- fputs(get_mode_name(mode), env->file);
+ fputs(symbol, env->file);
fputc(' ', env->file);
}
-static void write_tarval(io_env_t *env, tarval *tv)
+static void write_entity_ref(write_env_t *env, ir_entity *entity)
+{
+ write_long(env, get_entity_nr(entity));
+}
+
+static void write_type_ref(write_env_t *env, ir_type *type)
{
- char buf[1024];
- write_mode(env, get_tarval_mode(tv));
- tarval_snprintf(buf, sizeof(buf), tv);
- fputs(buf, env->file);
+ switch (get_type_tpop_code(type)) {
+ case tpo_unknown:
+ write_symbol(env, "unknown");
+ return;
+ case tpo_none:
+ write_symbol(env, "none");
+ return;
+ case tpo_code:
+ write_symbol(env, "code");
+ return;
+ default:
+ break;
+ }
+ write_long(env, get_type_nr(type));
+}
+
+static void write_string(write_env_t *env, const char *string)
+{
+ const char *c;
+ fputc('"', env->file);
+ for (c = string; *c != '\0'; ++c) {
+ switch (*c) {
+ case '\n':
+ fputc('\\', env->file);
+ fputc('n', env->file);
+ break;
+ case '"':
+ case '\\':
+ fputc('\\', env->file);
+ /* FALLTHROUGH */
+ default:
+ fputc(*c, env->file);
+ break;
+ }
+ }
+ fputc('"', env->file);
fputc(' ', env->file);
}
-static void write_align(io_env_t *env, ir_node *irn)
+static void write_ident(write_env_t *env, ident *id)
+{
+ write_string(env, get_id_str(id));
+}
+
+static void write_ident_null(write_env_t *env, ident *id)
{
- ir_align align;
+ if (id == NULL) {
+ fputs("NULL ", env->file);
+ } else {
+ write_ident(env, id);
+ }
+}
+
+static void write_mode_ref(write_env_t *env, ir_mode *mode)
+{
+ write_string(env, get_mode_name(mode));
+}
- if(is_Load(irn)) align = get_Load_align(irn);
- else if(is_Store(irn)) align = get_Store_align(irn);
- else assert(0 && "Invalid optype for write_align");
+static void write_tarval(write_env_t *env, ir_tarval *tv)
+{
+ 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(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_kind(io_env_t *env, ir_node *irn)
+static void write_cond_jmp_predicate(write_env_t *env, const ir_node *node)
{
- fputs(get_cond_kind_name(get_Cond_kind(irn)), env->file);
+ fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(node)), env->file);
fputc(' ', env->file);
}
-static void write_cond_jmp_predicate(io_env_t *env, ir_node *irn)
+static void write_relation(write_env_t *env, ir_relation relation)
{
- fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(irn)), env->file);
- fputc(' ', env->file);
+ 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(write_env_t *env)
+{
+ fputs("] ", env->file);
+}
+
+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(io_env_t *env, ir_initializer_t *ini)
+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);
fputs(get_initializer_kind_name(ini_kind), f);
fputc(' ', f);
- switch(ini_kind)
- {
- case IR_INITIALIZER_CONST:
- fprintf(f, "%ld ", get_irn_node_nr(get_initializer_const_value(ini)));
- break;
-
- case IR_INITIALIZER_TARVAL:
- write_tarval(env, get_initializer_tarval_value(ini));
- break;
+ switch (ini_kind) {
+ case IR_INITIALIZER_CONST:
+ write_node_ref(env, get_initializer_const_value(ini));
+ return;
- case IR_INITIALIZER_NULL:
- break;
+ case IR_INITIALIZER_TARVAL:
+ write_tarval(env, get_initializer_tarval_value(ini));
+ return;
- case IR_INITIALIZER_COMPOUND:
- {
- unsigned i, n = get_initializer_compound_n_entries(ini);
- fprintf(f, "%d ", n);
- for(i = 0; i < n; i++)
- write_initializer(env, get_initializer_compound_value(ini, i));
- break;
- }
+ case IR_INITIALIZER_NULL:
+ return;
- default:
- panic("Unknown initializer kind");
+ case IR_INITIALIZER_COMPOUND: {
+ size_t i, n = get_initializer_compound_n_entries(ini);
+ write_size_t(env, n);
+ for (i = 0; i < n; ++i)
+ write_initializer(env, get_initializer_compound_value(ini, i));
+ return;
}
+ }
+ 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_node *irn)
+static void write_volatility(write_env_t *env, ir_volatility vol)
{
- ir_volatility vol;
-
- if(is_Load(irn)) vol = get_Load_volatility(irn);
- else if(is_Store(irn)) vol = get_Store_volatility(irn);
- else assert(0 && "Invalid optype for write_volatility");
-
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_type_state(write_env_t *env, ir_type_state state)
{
- fprintf(env->file, "\t%s %ld %s \"%s\" %u %u %s %s ",
- is_frame_type(tp) ? "frametype" : is_value_param_type(tp) ? "valuetype" : "type",
- get_type_nr(tp),
- get_type_tpop_name(tp),
- get_type_name(tp),
- get_type_size_bytes(tp),
- get_type_alignment_bytes(tp),
- get_type_state_name(get_type_state(tp)),
- get_visibility_name(get_type_visibility(tp)));
+ fputs(get_type_state_name(state), env->file);
+ fputc(' ', env->file);
}
-static void export_type_pre(io_env_t *env, ir_type *tp)
+static void write_visibility(write_env_t *env, ir_visibility visibility)
{
- FILE *f = env->file;
- int i;
-
- // skip types to be handled by post walker
- switch(get_type_tpop_code(tp))
- {
- case tpo_array:
- case tpo_method:
- case tpo_pointer:
- return;
- }
-
- export_type_common(env, tp);
+ fputs(get_visibility_name(visibility), env->file);
+ fputc(' ', env->file);
+}
- switch(get_type_tpop_code(tp))
- {
- case tpo_class:
- /* TODO: inheritance stuff not supported yet */
- printf("Inheritance of classes not supported yet!\n");
- break;
+static void write_mode_arithmetic(write_env_t *env, ir_mode_arithmetic arithmetic)
+{
+ fputs(get_mode_arithmetic_name(arithmetic), env->file);
+ fputc(' ', env->file);
+}
- case tpo_primitive:
- write_mode(env, get_type_mode(tp));
- break;
+static void write_type(write_env_t *env, ir_type *tp);
+static void write_entity(write_env_t *env, ir_entity *entity);
- case tpo_struct:
- 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_union:
- break;
+static void write_type_primitive(write_env_t *env, ir_type *tp)
+{
+ ir_type *base_type = get_primitive_base_type(tp);
- case tpo_unknown:
- break;
+ if (base_type != NULL)
+ write_type(env, base_type);
- default:
- printf("export_type_pre: Unknown type code \"%s\".\n", get_type_tpop_name(tp));
- break;
- }
- fputc('\n', f);
+ write_type_common(env, tp);
+ write_mode_ref(env, get_type_mode(tp));
+ if (base_type == NULL)
+ base_type = get_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;
- int i;
+ 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:
- return;
+ 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 whether
+ * 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:
- {
- int n = get_array_n_dimensions(tp);
- fprintf(f, "%i %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);
+ for (i = 0; i < n_members; ++i) {
+ ir_entity *member = get_compound_member(tp, i);
+ write_entity(env, member);
+ }
+}
- if(is_Const(lower)) fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(lower)));
- else panic("Lower array bound is not constant");
+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;
- if(is_Const(upper)) fprintf(f, "%ld ", get_tarval_long(get_Const_tarval(upper)));
- else if(is_Unknown(upper)) fputs("unknown ", f);
- else panic("Upper array bound is not constant");
- }
- break;
- }
+ write_type(env, element_type);
- case tpo_method:
- {
- int nparams = get_method_n_params(tp);
- int nresults = get_method_n_ress(tp);
- fprintf(f, "0x%X 0x%X %i %i ", get_method_calling_convention(tp),
- get_method_additional_properties(tp), nparams, nresults);
- for(i = 0; i < nparams; i++)
- fprintf(f, "%ld ", get_type_nr(get_method_param_type(tp, i)));
- for(i = 0; i < nresults; i++)
- fprintf(f, "%ld ", get_type_nr(get_method_res_type(tp, i)));
- fprintf(f, "%d ", get_method_first_variadic_param_index(tp));
- break;
- }
+ 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);
- case tpo_pointer:
- write_mode(env, get_type_mode(tp));
- fprintf(f, "%ld ", get_type_nr(get_pointer_points_to_type(tp)));
- break;
+ if (is_Const(lower))
+ write_long(env, get_tarval_long(get_Const_tarval(lower)));
+ else
+ panic("Lower array bound is not constant");
- default:
- printf("export_type: Unknown type code \"%s\".\n", get_type_tpop_name(tp));
- break;
- }
- fputc('\n', f);
-}
-
-static void export_entity(io_env_t *env, ir_entity *ent)
-{
- ir_type *owner = get_entity_owner(ent);
- fprintf(env->file, "\tentity %ld \"%s\" \"%s\" %ld %ld %d %u %s %s %s %s %s ",
- get_entity_nr(ent),
- get_entity_name(ent),
- ent->ld_name ? get_id_str(ent->ld_name) : "",
- get_type_nr(get_entity_type(ent)),
- get_type_nr(owner),
- get_entity_offset(ent),
- (unsigned) get_entity_offset_bits_remainder(ent),
- get_allocation_name(get_entity_allocation(ent)),
- get_visibility_name(get_entity_visibility(ent)),
- get_variability_name(get_entity_variability(ent)),
- get_peculiarity_name(get_entity_peculiarity(ent)),
- get_volatility_name(get_entity_volatility(ent)));
-
- // TODO: inheritance stuff for class entities not supported yet
- if(is_Class_type(owner) && owner != get_glob_type())
- printf("Inheritance of class entities not supported yet!\n");
-
- if(get_entity_variability(ent) != variability_uninitialized
- && get_entity_visibility(ent) != visibility_external_allocated)
- {
- if(is_compound_entity(ent))
- {
- if(has_entity_initializer(ent))
- {
- fputs("initializer ", env->file);
- write_initializer(env, get_entity_initializer(ent));
- }
- else
- {
- int i, n = get_compound_ent_n_values(ent);
- fputs("noninitializer ", env->file);
- fprintf(env->file, "%d ", 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));
- }
- }
- }
+ if (is_Const(upper))
+ write_long(env, get_tarval_long(get_Const_tarval(upper)));
+ else if (is_Unknown(upper))
+ write_symbol(env, "unknown");
else
- {
- ir_node *irn = get_atomic_ent_value(ent);
- fprintf(env->file, "%ld ", get_irn_node_nr(irn));
- }
+ 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);
}
-static void export_type_or_ent_pre(type_or_ent tore, void *ctx)
+static void write_type_method(write_env_t *env, ir_type *tp)
{
- io_env_t *env = (io_env_t *) ctx;
- if(get_kind(tore.typ) == k_type)
- export_type_pre(env, tore.typ);
+ size_t nparams = get_method_n_params(tp);
+ size_t nresults = get_method_n_ress(tp);
+ size_t i;
+
+ 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);
}
-static void export_type_or_ent_post(type_or_ent tore, void *ctx)
+static void write_type_pointer(write_env_t *env, ir_type *tp)
{
- io_env_t *env = (io_env_t *) ctx;
-
- switch(get_kind(tore.ent))
- {
- case k_entity:
- export_entity(env, tore.ent);
- break;
+ ir_type *points_to = get_pointer_points_to_type(tp);
- case k_type:
- export_type_post(env, tore.typ);
- break;
+ write_type(env, points_to);
- default:
- printf("export_type_or_ent_post: Unknown type or entity.\n");
- break;
- }
+ 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 export_node(ir_node *irn, void *ctx)
+static void write_type_enumeration(write_env_t *env, ir_type *tp)
{
- io_env_t *env = (io_env_t *) ctx;
- int i, n;
- unsigned opcode = get_irn_opcode(irn);
+ write_type_common(env, tp);
+ write_ident_null(env, get_enumeration_ident(tp));
+ fputc('\n', env->file);
+}
- if(env->ignoreblocks && opcode == iro_Block)
+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;
- n = get_irn_arity(irn);
-
- fprintf(env->file, "\t%s %ld [ ", get_irn_opname(irn), get_irn_node_nr(irn));
-
- for(i = -1; 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 {
- fprintf(env->file, "%ld ", get_irn_node_nr(pred));
- }
- }
-
- fprintf(env->file, "] { ");
+ case tpo_union:
+ case tpo_struct:
+ case tpo_class:
+ write_type_compound(env, tp);
+ return;
- switch(opcode)
- {
- #include "gen_irio_export.inl"
+ 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;
}
- fputs("}\n", env->file);
+ panic("can't write invalid type %+F\n", tp);
}
-static void export_modes(io_env_t *env)
+static void write_entity(write_env_t *env, ir_entity *ent)
{
- int i, n_modes = get_irp_n_modes();
+ 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);
- fputs("modes {\n", env->file);
+ if (entity_visited(ent))
+ return;
+ mark_entity_visited(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;
+ case IR_ENTITY_UNKNOWN:
+ write_symbol(env, "unknown");
+ write_long(env, get_entity_nr(ent));
+ return;
+ }
+ write_long(env, get_entity_nr(ent));
- for(i = 0; i < n_modes; i++)
- {
- ir_mode *mode = get_irp_mode(i);
- switch(get_mode_sort(mode))
- {
- case irms_auxiliary:
- case irms_control_flow:
- case irms_memory:
- case irms_internal_boolean:
- // skip "internal" modes, which may not be user defined
- continue;
+ 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));
}
+ }
- fprintf(env->file, "\tmode \"%s\" 0x%X %d %d %s %d %d ", get_mode_name(mode),
- get_mode_sort(mode), get_mode_size_bits(mode), get_mode_sign(mode),
- get_mode_arithmetic_name(get_mode_arithmetic(mode)), get_mode_modulo_shift(mode),
- get_mode_n_vector_elems(mode));
- if(mode_is_reference(mode))
- {
- write_mode(env, get_reference_mode_signed_eq(mode));
- write_mode(env, get_reference_mode_unsigned_eq(mode));
+ write_visibility(env, visibility);
+ write_list_begin(env);
+ if (linkage & IR_LINKAGE_CONSTANT)
+ write_symbol(env, "constant");
+ if (linkage & IR_LINKAGE_WEAK)
+ write_symbol(env, "weak");
+ if (linkage & IR_LINKAGE_GARBAGE_COLLECT)
+ write_symbol(env, "garbage_collect");
+ if (linkage & IR_LINKAGE_MERGE)
+ write_symbol(env, "merge");
+ if (linkage & IR_LINKAGE_HIDDEN_USER)
+ 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 {
+ write_symbol(env, "none");
}
- fputc('\n', 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_UNKNOWN:
+ case IR_ENTITY_LABEL:
+ case IR_ENTITY_METHOD:
+ break;
}
- fputs("}\n\n", env->file);
+ fputc('\n', env->file);
}
-/** Exports the whole irp to the given file in a textual form. */
-void ir_export(const char *filename)
+static void write_switch_table(write_env_t *env, const ir_switch_table *table)
{
- io_env_t env;
- int i, n_irgs = get_irp_n_irgs();
+ size_t n_entries = ir_switch_table_get_n_entries(table);
+ size_t i;
- env.file = fopen(filename, "wt");
- if(!env.file)
- {
- perror(filename);
- return;
+ 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);
}
+}
- export_modes(&env);
-
- fputs("typegraph {\n", env.file);
-
- type_walk_plus_frames(export_type_or_ent_pre, export_type_or_ent_post, &env);
- /* TODO: Visit frame types and "types for value params"? */
-
- for(i = 0; i < n_irgs; i++)
- {
- ir_graph *irg = get_irp_irg(i);
- ir_type *valuetype = get_irg_value_param_type(irg);
-
- fprintf(env.file, "}\n\nirg %ld %ld %ld {\n", get_entity_nr(get_irg_entity(irg)),
- get_type_nr(get_irg_frame_type(irg)),
- valuetype == NULL ? -1 : get_type_nr(valuetype));
-
- env.ignoreblocks = 0;
- irg_block_walk_graph(irg, NULL, export_node, &env);
-
- env.ignoreblocks = 1;
- irg_walk_anchors(irg, NULL, export_node, &env);
+static void write_pred_refs(write_env_t *env, const ir_node *node, int from)
+{
+ 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);
}
-
- 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);
-
- fclose(env.file);
+ write_list_end(env);
}
-/** Exports the given irg to the given file. */
-void ir_export_irg(ir_graph *irg, const char *filename)
+static void write_node_nr(write_env_t *env, const ir_node *node)
{
- io_env_t env;
+ write_long(env, get_irn_node_nr(node));
+}
- env.file = fopen(filename, "wt");
- if(!env.file)
- {
- perror(filename);
- return;
+static void write_ASM(write_env_t *env, const ir_node *node)
+{
+ write_symbol(env, "ASM");
+ write_node_nr(env, node);
+ write_node_nr(env, get_nodes_block(node));
+ write_node_nr(env, get_ASM_mem(node));
+
+ write_ident(env, get_ASM_text(node));
+ write_list_begin(env);
+ ir_asm_constraint *input_constraints = get_ASM_input_constraints(node);
+ int n_inputs = get_ASM_n_inputs(node);
+ for (int i = 0; i < n_inputs; ++i) {
+ const ir_asm_constraint *constraint = &input_constraints[i];
+ write_unsigned(env, constraint->pos);
+ write_ident(env, constraint->constraint);
+ write_mode_ref(env, constraint->mode);
}
+ write_list_end(env);
+
+ write_list_begin(env);
+ ir_asm_constraint *output_constraints = get_ASM_output_constraints(node);
+ size_t n_output_constraints = get_ASM_n_output_constraints(node);
+ for (size_t i = 0; i < n_output_constraints; ++i) {
+ const ir_asm_constraint *constraint = &output_constraints[i];
+ write_unsigned(env, constraint->pos);
+ write_ident(env, constraint->constraint);
+ write_mode_ref(env, constraint->mode);
+ }
+ write_list_end(env);
+
+ write_list_begin(env);
+ ident **clobbers = get_ASM_clobbers(node);
+ size_t n_clobbers = get_ASM_n_clobbers(node);
+ for (size_t i = 0; i < n_clobbers; ++i) {
+ ident *clobber = clobbers[i];
+ write_ident(env, clobber);
+ }
+ write_list_end(env);
- export_modes(&env);
-
- fputs("typegraph {\n", env.file);
+ write_pin_state(env, get_irn_pinned(node));
+ write_pred_refs(env, node, n_ASM_max+1);
+}
- type_walk_irg(irg, export_type_or_ent_pre, export_type_or_ent_post, &env);
+static void write_Phi(write_env_t *env, const ir_node *node)
+{
+ 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, "}\n\nirg %ld {\n", get_entity_nr(get_irg_entity(irg)));
+static void write_Block(write_env_t *env, const ir_node *node)
+{
+ ir_entity *entity = get_Block_entity(node);
- env.ignoreblocks = 0;
- irg_block_walk_graph(irg, NULL, export_node, &env);
+ 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);
+}
- env.ignoreblocks = 1;
- irg_walk_anchors(irg, NULL, export_node, &env);
+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);
+}
- /* TODO: Only output needed constants */
- fputs("}\n\nconstirg {\n", env.file);
- walk_const_code(NULL, export_node, &env);
- fputs("}\n", env.file);
+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);
- fclose(env.file);
+ 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));
}
-static void save_lex_state(io_env_t *env, lex_state_t *state)
+typedef void write_node_func(write_env_t *env, ir_node const *node);
+
+static void register_node_writer(ir_op *op, write_node_func *func)
{
- state->offs = ftell(env->file);
- state->line = env->line;
- state->col = env->col;
+ set_generic_function_ptr(op, func);
}
-static void restore_lex_state(io_env_t *env, lex_state_t *state)
+static void writers_init(void)
{
- fseek(env->file, state->offs, SEEK_SET);
- env->line = state->line;
- env->col = state->col;
+ ir_clear_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 int read_c(io_env_t *env)
+static void write_node(const ir_node *node, write_env_t *env)
{
- int ch = fgetc(env->file);
- switch(ch)
- {
- case '\t':
- env->col += 4;
- break;
-
- case '\n':
- env->col = 0;
- env->line++;
- break;
+ ir_op *const op = get_irn_op(node);
+ write_node_func *const func = get_generic_function_ptr(write_node_func, op);
- default:
- env->col++;
- break;
- }
- return ch;
+ fputc('\t', env->file);
+ if (func == NULL)
+ panic("No write_node_func for %+F", node);
+ func(env, node);
+ fputc('\n', env->file);
}
-/** Returns the first non-whitespace character or EOF. **/
-static int skip_ws(io_env_t *env)
-{
- while(1)
- {
- int ch = read_c(env);
- switch(ch)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- break;
+static void write_node_recursive(ir_node *node, write_env_t *env);
- default:
- return ch;
- }
+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);
}
}
-static void skip_to(io_env_t *env, char to_ch)
+/**
+ * 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)
{
- int ch;
- do
- {
- ch = read_c(env);
+ if (irn_visited_else_mark(node))
+ return;
+
+ if (!is_Block(node)) {
+ write_node_recursive(get_nodes_block(node), env);
}
- while(ch != to_ch && ch != EOF);
+ /* 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 int expect_char(io_env_t *env, char ch)
-{
- int curch = skip_ws(env);
- if(curch != ch)
- {
- printf("Unexpected char '%c', expected '%c' in line %i:%i\n", curch, ch, env->line, env->col);
- return 0;
+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");
}
- return 1;
}
-#define EXPECT(c) if(expect_char(env, (c))) {} else return 0
-#define EXPECT_OR_EXIT(c) if(expect_char(env, (c))) {} else exit(1)
-
-inline static const char *read_str_to(io_env_t *env, char *buf, size_t bufsize)
+static void write_modes(write_env_t *env)
{
+ size_t n_modes = ir_get_n_modes();
size_t i;
- for(i = 0; i < bufsize - 1; i++)
- {
- int ch = read_c(env);
- if(ch == EOF) break;
- switch(ch)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- if(i != 0)
- goto endofword;
- i--; // skip whitespace
- break;
- default:
- buf[i] = ch;
- break;
+ write_symbol(env, "modes");
+ fputs("{\n", env->file);
+
+ for (i = 0; i < n_modes; i++) {
+ ir_mode *mode = ir_get_mode(i);
+ 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);
}
-endofword:
- buf[i] = 0;
- return buf;
+
+ fputs("}\n\n", env->file);
}
-static const char *read_str(io_env_t *env)
+static void write_program(write_env_t *env)
{
- static char buf[1024];
- return read_str_to(env, buf, sizeof(buf));
+ ir_segment_t s;
+ size_t n_asms = get_irp_n_asms();
+ size_t i;
+
+ write_symbol(env, "program");
+ write_scope_begin(env);
+ if (irp_prog_name_is_set()) {
+ fputc('\t', env->file);
+ write_symbol(env, "name");
+ write_string(env, get_irp_name());
+ fputc('\n', env->file);
+ }
+
+ for (s = IR_SEGMENT_FIRST; s <= IR_SEGMENT_LAST; ++s) {
+ ir_type *segment_type = get_segment_type(s);
+ fputc('\t', env->file);
+ write_symbol(env, "segment_type");
+ write_symbol(env, get_segment_name(s));
+ if (segment_type == NULL) {
+ write_symbol(env, "NULL");
+ } else {
+ 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);
+ }
+ write_scope_end(env);
}
-static const char *read_qstr_to(io_env_t *env, char *buf, size_t bufsize)
+int ir_export(const char *filename)
{
+ FILE *file = fopen(filename, "wt");
+ int res = 0;
+ if (file == NULL) {
+ perror(filename);
+ return 1;
+ }
+
+ 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;
- EXPECT_OR_EXIT('\"');
- for(i = 0; i < bufsize - 1; i++)
- {
- int ch = read_c(env);
- if(ch == EOF)
- {
- printf("Unexpected end of quoted string!\n");
+
+ 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_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)
+{
+ write_env_t my_env;
+ write_env_t *env = &my_env;
+ size_t i, n_irgs = get_irp_n_irgs();
+
+ memset(env, 0, sizeof(*env));
+ env->file = file;
+ env->write_queue = new_pdeq();
+
+ writers_init();
+ write_modes(env);
+
+ write_typegraph(env);
+
+ for (i = 0; i < n_irgs; i++) {
+ ir_graph *irg = get_irp_irg(i);
+ write_irg(env, irg);
+ }
+
+ 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);
+
+ write_program(env);
+
+ del_pdeq(env->write_queue);
+}
+
+
+
+static void read_c(read_env_t *env)
+{
+ int c = fgetc(env->file);
+ env->c = c;
+ if (c == '\n')
+ env->line++;
+}
+
+/** Returns the first non-whitespace character or EOF. **/
+static void skip_ws(read_env_t *env)
+{
+ while (true) {
+ switch (env->c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ read_c(env);
+ continue;
+
+ default:
+ return;
+ }
+ }
+}
+
+static void skip_to(read_env_t *env, char to_ch)
+{
+ while (env->c != to_ch && env->c != EOF) {
+ read_c(env);
+ }
+}
+
+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 false;
+ }
+ read_c(env);
+ return true;
+}
+
+#define EXPECT(c) if (expect_char(env, (c))) {} else return
+
+static char *read_word(read_env_t *env)
+{
+ skip_ws(env);
+
+ assert(obstack_object_size(&env->obst) == 0);
+ while (true) {
+ int c = env->c;
+ switch (c) {
+ case EOF:
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ goto endofword;
+
+ default:
+ obstack_1grow(&env->obst, c);
+ break;
+ }
+ read_c(env);
+ }
+
+endofword:
+ obstack_1grow(&env->obst, '\0');
+ return (char*)obstack_finish(&env->obst);
+}
+
+static char *read_string(read_env_t *env)
+{
+ skip_ws(env);
+ if (env->c != '"') {
+ parse_error(env, "Expected string, got '%c'\n", env->c);
+ exit(1);
+ }
+ read_c(env);
+
+ assert(obstack_object_size(&env->obst) == 0);
+ while (env->c != '"') {
+ if (env->c == EOF) {
+ parse_error(env, "Unexpected EOF while parsing string\n");
exit(1);
}
- if(ch == '\"') break;
- buf[i] = ch;
+ if (env->c == '\\') {
+ read_c(env);
+ switch (env->c) {
+ case 'n':
+ obstack_1grow(&env->obst, '\n');
+ break;
+ case '"':
+ case '\\':
+ obstack_1grow(&env->obst, env->c);
+ break;
+ default:
+ parse_error(env, "Unknown escape sequence '\\%c'\n", env->c);
+ exit(1);
+ }
+ } else {
+ obstack_1grow(&env->obst, env->c);
+ }
+ read_c(env);
+ }
+ read_c(env);
+ obstack_1grow(&env->obst, 0);
+
+ return (char*)obstack_finish(&env->obst);
+}
+
+static ident *read_ident(read_env_t *env)
+{
+ char *str = read_string(env);
+ ident *res = new_id_from_str(str);
+ obstack_free(&env->obst, str);
+ 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(read_env_t *env)
+{
+ skip_ws(env);
+ if (env->c == 'N') {
+ char *str = read_word(env);
+ if (strcmp(str, "NULL") == 0) {
+ obstack_free(&env->obst, str);
+ return NULL;
+ }
+ } else if (env->c == '"') {
+ return read_string(env);
}
- if(i == bufsize - 1)
- {
- printf("Quoted string too long!\n");
+
+ parse_error(env, "Expected \"string\" or NULL\n");
+ exit(1);
+}
+
+static ident *read_ident_null(read_env_t *env)
+{
+ ident *res;
+ char *str = read_string_null(env);
+ if (str == NULL)
+ return NULL;
+
+ res = new_id_from_str(str);
+ obstack_free(&env->obst, str);
+ return res;
+}
+
+static long read_long(read_env_t *env)
+{
+ long result;
+ char *str;
+
+ skip_ws(env);
+ if (!isdigit(env->c) && env->c != '-') {
+ parse_error(env, "Expected number, got '%c'\n", env->c);
exit(1);
}
- buf[i] = 0;
- return buf;
+
+ assert(obstack_object_size(&env->obst) == 0);
+ do {
+ obstack_1grow(&env->obst, env->c);
+ read_c(env);
+ } while (isdigit(env->c));
+ obstack_1grow(&env->obst, 0);
+
+ str = (char*)obstack_finish(&env->obst);
+ result = atol(str);
+ obstack_free(&env->obst, str);
+
+ return result;
}
-static const char *read_qstr(io_env_t *env)
+static int read_int(read_env_t *env)
{
- static char buf[1024];
- return read_qstr_to(env, buf, sizeof(buf));
+ return (int) read_long(env);
}
-static long read_long2(io_env_t *env, char **endptr)
+static unsigned read_unsigned(read_env_t *env)
{
- static char buf[1024];
- return strtol(read_str_to(env, buf, sizeof(buf)), endptr, 0);
+ return (unsigned) read_long(env);
}
-static long read_long(io_env_t *env)
+static size_t read_size_t(read_env_t *env)
{
- return read_long2(env, NULL);
+ /* FIXME */
+ return (size_t) read_unsigned(env);
}
-static ir_node *get_node_or_null(io_env_t *env, long nodenr)
+static void expect_list_begin(read_env_t *env)
{
- 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 %i:%i\n", nodenr, env->line, env->col);
+ skip_ws(env);
+ if (env->c != '[') {
+ parse_error(env, "Expected list, got '%c'\n", env->c);
+ exit(1);
}
- return node;
+ read_c(env);
}
-static ir_node *get_node(io_env_t *env, long nodenr)
+static bool list_has_next(read_env_t *env)
{
- ir_node *node = get_node_or_null(env, nodenr);
- if(!node)
- panic("Unknown node: %ld in line %i:%i\n", nodenr, env->line, env->col);
+ if (feof(env->file)) {
+ parse_error(env, "Unexpected EOF while reading list");
+ exit(1);
+ }
+ skip_ws(env);
+ if (env->c == ']') {
+ read_c(env);
+ return false;
+ }
- return node;
+ return true;
}
-static ir_node *get_node_or_dummy(io_env_t *env, long nodenr)
+static void *get_id(read_env_t *env, long id)
{
- ir_node *node = get_node_or_null(env, nodenr);
- if(!node)
- {
- node = new_Dummy(mode_X);
- set_id(env, nodenr, node);
+ id_entry key, *entry;
+ key.id = id;
+
+ entry = set_find(id_entry, 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;
+ (void)set_insert(id_entry, 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) {
+ parse_error(env, "Irn ID %ld collides with something else\n",
+ nodenr);
+ return NULL;
}
return node;
}
-static ir_type *get_type(io_env_t *env, long typenr)
+static ir_type *get_type(read_env_t *env, long typenr)
{
ir_type *type = (ir_type *) get_id(env, typenr);
- if(!type)
- {
- panic("Unknown type: %ld in line %i:%i\n", typenr, env->line, env->col);
+ if (type == NULL) {
+ parse_error(env, "Type %ld not defined (yet?)\n", typenr);
+ return get_unknown_type();
}
- else if(type->kind != k_type)
- {
- panic("Type ID %ld collides with something else in line %i:%i\n", typenr, env->line, env->col);
+ if (type->kind != k_type) {
+ parse_error(env, "Object %ld is not a type (but should be)\n", typenr);
+ return get_unknown_type();
}
return type;
}
-static ir_type *read_type(io_env_t *env)
+static ir_type *read_type_ref(read_env_t *env)
+{
+ char *str = read_word(env);
+ if (strcmp(str, "none") == 0) {
+ obstack_free(&env->obst, str);
+ return get_none_type();
+ }
+ if (strcmp(str, "unknown") == 0) {
+ obstack_free(&env->obst, str);
+ return get_unknown_type();
+ }
+ if (strcmp(str, "code") == 0) {
+ obstack_free(&env->obst, str);
+ return get_code_type();
+ }
+ long nr = atol(str);
+ obstack_free(&env->obst, str);
+
+ return get_type(env, nr);
+}
+
+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"),
+ get_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)
- {
- printf("Unknown entity: %ld in line %i:%i\n", entnr, env->line, env->col);
- exit(1);
+ if (entity == NULL) {
+ parse_error(env, "unknown entity: %ld\n", entnr);
+ return create_error_entity();
}
- else if(entity->kind != k_entity)
- {
- panic("Entity ID %ld collides with something else in line %i:%i\n", entnr, env->line, env->col);
+ 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)
{
- static char buf[128];
- int i, n;
-
- read_str_to(env, buf, sizeof(buf));
+ char *str = read_string(env);
+ size_t n = ir_get_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(buf, get_mode_name(mode)))
+ for (i = 0; i < n; i++) {
+ ir_mode *mode = ir_get_mode(i);
+ if (strcmp(str, get_mode_name(mode)) == 0) {
+ obstack_free(&env->obst, str);
return mode;
+ }
}
- printf("Unknown mode \"%s\" in line %i:%i\n", buf, env->line, env->col);
+ parse_error(env, "unknown mode \"%s\"\n", str);
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_initializer: return "initializer kind";
- case tt_iro: return "opcode";
- case tt_peculiarity: return "peculiarity";
- case tt_pin_state: return "pin state";
- case tt_tpo: return "type";
- case tt_type_state: return "type state";
- case tt_variability: return "variability";
- case tt_visibility: return "visibility";
- case tt_volatility: return "volatility";
- default: return "<UNKNOWN>";
+ switch (typetag) {
+ 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_keyword: return "keyword";
+ case tt_linkage: return "linkage";
+ case tt_mode_arithmetic: return "mode_arithmetic";
+ case tt_pin_state: return "pin state";
+ case tt_segment: return "segment";
+ case tt_throws: return "throws";
+ case tt_tpo: return "type";
+ case tt_type_state: return "type state";
+ case tt_visibility: return "visibility";
+ case tt_volatility: return "volatility";
+ case tt_where_alloc: return "where alloc";
}
+ return "<UNKNOWN>";
}
/**
* 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)
{
- static char buf[128];
- unsigned code = symbol(read_str_to(env, buf, sizeof(buf)), typetag);
- if(code != SYMERROR)
+ char *str = read_word(env);
+ unsigned code = symbol(str, typetag);
+
+ if (code != SYMERROR) {
+ obstack_free(&env->obst, str);
return code;
+ }
- printf("Invalid %s: \"%s\" in %i:%i\n", get_typetag_name(typetag), buf, env->line, env->col);
+ parse_error(env, "invalid %s: \"%s\"\n", get_typetag_name(typetag), str);
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_kind(env) ((cond_kind) read_enum(env, tt_cond_kind))
-#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_visibility(env) ((ir_visibility) read_enum(env, tt_visibility))
-#define read_volatility(env) ((ir_volatility) read_enum(env, tt_volatility))
-
-static ir_cons_flags get_cons_flags(io_env_t *env)
-{
- ir_cons_flags flags = cons_none;
-
- op_pin_state pinstate = read_pin_state(env);
- switch(pinstate)
- {
- case op_pin_state_floats: flags |= cons_floats; break;
- case op_pin_state_pinned: break;
- default:
- panic("Error in %i:%i: Invalid pinstate: %s", env->line, env->col, get_op_pin_state_name(pinstate));
- }
+static ir_align read_align(read_env_t *env)
+{
+ return (ir_align)read_enum(env, tt_align);
+}
- if(read_volatility(env) == volatility_is_volatile) flags |= cons_volatile;
- if(read_align(env) == align_non_aligned) flags |= cons_unaligned;
+static ir_builtin_kind read_builtin_kind(read_env_t *env)
+{
+ return (ir_builtin_kind)read_enum(env, tt_builtin_kind);
+}
- return flags;
+static cond_jmp_predicate read_cond_jmp_predicate(read_env_t *env)
+{
+ return (cond_jmp_predicate)read_enum(env, tt_cond_jmp_predicate);
}
-static tarval *read_tv(io_env_t *env)
+static ir_initializer_kind_t read_initializer_kind(read_env_t *env)
{
- static char buf[128];
- ir_mode *tvmode = read_mode(env);
- read_str_to(env, buf, sizeof(buf));
- return new_tarval_from_str(buf, strlen(buf), tvmode);
+ return (ir_initializer_kind_t)read_enum(env, tt_initializer);
}
-static ir_initializer_t *read_initializer(io_env_t *env)
+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 bool read_throws(read_env_t *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 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;
+ 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_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)
{
- FILE *f = env->file;
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);
+ switch (ini_kind) {
+ case IR_INITIALIZER_CONST: {
+ 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));
+ case IR_INITIALIZER_TARVAL:
+ return create_initializer_tarval(read_tarval(env));
- case IR_INITIALIZER_NULL:
- return get_initializer_null();
+ case IR_INITIALIZER_NULL:
+ return get_initializer_null();
- case IR_INITIALIZER_COMPOUND:
- {
- unsigned i, n = (unsigned) read_long(env);
- ir_initializer_t *ini = create_initializer_compound(n);
- for(i = 0; i < n; i++)
- {
- ir_initializer_t *curini = read_initializer(env);
- set_initializer_compound_value(ini, i, curini);
- }
- return ini;
+ case IR_INITIALIZER_COMPOUND: {
+ size_t i, n = read_size_t(env);
+ ir_initializer_t *ini = create_initializer_compound(n);
+ for (i = 0; i < n; i++) {
+ ir_initializer_t *curini = read_initializer(env);
+ set_initializer_compound_value(ini, i, curini);
}
-
- default:
- panic("Unknown initializer kind");
+ return ini;
+ }
}
-}
+ panic("Unknown initializer kind");
+}
/** Reads a type description and remembers it by its id. */
-static void import_type(io_env_t *env, keyword_t kwkind)
+static void read_type(read_env_t *env)
{
- int i;
- ir_type *type;
long typenr = read_long(env);
- const char *tpop = read_str(env);
- const char *name = read_qstr(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);
- ir_visibility vis = read_visibility(env);
-
- ident *id = new_id_from_str(name);
+ unsigned flags = (unsigned) read_long(env);
+ ir_type *type;
- const char *kindstr;
+ switch (tpop) {
+ case tpo_array: {
+ 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);
+ set_array_lower_bound_int(type, i, lowerbound);
+ }
+ obstack_free(&env->obst, str);
- if(kwkind == kw_frametype)
- {
- if(symbol(tpop, tt_tpo) != tpo_class)
- {
- printf("Frame type must be a class type in line %i:%i\n", env->line, env->col);
- skip_to(env, '\n');
- return;
+ str = read_word(env);
+ if (strcmp(str, "unknown") != 0) {
+ long upperbound = atol(str);
+ set_array_upper_bound_int(type, i, upperbound);
+ }
+ obstack_free(&env->obst, str);
}
- type = new_type_frame(id);
- set_type_size_bytes(type, size);
+ element_entity_nr = read_long(env);
+ element_entity = get_array_element_entity(type);
+ set_id(env, element_entity_nr, element_entity);
- kindstr = "frametype";
+ set_type_size_bytes(type, size);
+ goto finish_type;
}
- else if(kwkind == kw_valuetype)
- {
- if(symbol(tpop, tt_tpo) != tpo_struct)
- {
- printf("Value type must be a struct type in line %i:%i\n", env->line, env->col);
- skip_to(env, '\n');
- return;
- }
- type = new_type_value(id);
+ case tpo_class: {
+ ident *id = read_ident_null(env);
+
+ if (typenr == (long) IR_SEGMENT_GLOBAL)
+ type = get_glob_type();
+ else
+ type = new_type_class(id);
set_type_size_bytes(type, size);
+ goto finish_type;
+ }
- kindstr = "valuetype";
- }
- else
- {
- switch(symbol(tpop, tt_tpo))
- {
- 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(id, ndims, elemtype);
- for(i = 0; i < ndims; i++)
- {
- const char *str = read_str(env);
- if(strcmp(str, "unknown"))
- {
- long lowerbound = strtol(str, NULL, 0);
- set_array_lower_bound_int(type, i, lowerbound);
- }
- str = read_str(env);
- if(strcmp(str, "unknown"))
- {
- long upperbound = strtol(str, NULL, 0);
- set_array_upper_bound_int(type, i, upperbound);
- }
- }
- set_type_size_bytes(type, size);
- break;
- }
+ case tpo_method: {
+ 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;
+ ir_variadicity variadicity;
- case tpo_class:
- type = new_type_class(id);
- set_type_size_bytes(type, size);
- break;
+ type = new_type_method(nparams, nresults);
- case tpo_method:
- {
- unsigned callingconv = (unsigned) read_long(env);
- unsigned addprops = (unsigned) read_long(env);
- int nparams = (int) read_long(env);
- int nresults = (int) read_long(env);
- int variaindex;
-
- type = new_type_method(id, nparams, nresults);
-
- for(i = 0; i < nparams; i++)
- {
- long typenr = read_long(env);
- ir_type *paramtype = get_type(env, typenr);
-
- set_method_param_type(type, i, paramtype);
- }
- for(i = 0; i < nresults; i++)
- {
- long typenr = read_long(env);
- ir_type *restype = get_type(env, typenr);
-
- set_method_res_type(type, i, restype);
- }
-
- variaindex = (int) read_long(env);
- if(variaindex != -1)
- {
- set_method_variadicity(type, variadicity_variadic);
- if(variaindex != nparams)
- set_method_first_variadic_param_index(type, variaindex);
- }
-
- set_method_calling_convention(type, callingconv);
- set_method_additional_properties(type, addprops);
- break;
- }
+ for (i = 0; i < nparams; i++) {
+ long ptypenr = read_long(env);
+ ir_type *paramtype = get_type(env, ptypenr);
- case tpo_pointer:
- {
- ir_mode *mode = read_mode(env);
- ir_type *pointsto = get_type(env, read_long(env));
- type = new_type_pointer(id, pointsto, mode);
- break;
- }
+ set_method_param_type(type, i, paramtype);
+ }
+ for (i = 0; i < nresults; i++) {
+ long ptypenr = read_long(env);
+ ir_type *restype = get_type(env, ptypenr);
- case tpo_primitive:
- {
- ir_mode *mode = read_mode(env);
- type = new_type_primitive(id, mode);
- break;
- }
+ set_method_res_type(type, i, restype);
+ }
- case tpo_struct:
- type = new_type_struct(id);
- set_type_size_bytes(type, size);
- break;
+ variadicity = (ir_variadicity) read_long(env);
+ set_method_variadicity(type, variadicity);
- case tpo_union:
- type = new_type_union(id);
- set_type_size_bytes(type, size);
- break;
+ set_method_calling_convention(type, callingconv);
+ set_method_additional_properties(type, addprops);
+ goto finish_type;
+ }
- case tpo_unknown:
- return; // ignore unknown type
+ case tpo_pointer: {
+ 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);
+ goto finish_type;
+ }
- default:
- if(typenr != 0) // ignore global type
- printf("Unknown type kind: \"%s\" in line %i:%i\n", tpop, env->line, env->col);
- skip_to(env, '\n');
- return;
+ case tpo_primitive: {
+ ir_mode *mode = read_mode_ref(env);
+ ir_type *base_type = read_type_ref(env);
+ type = new_type_primitive(mode);
+ if (base_type != get_none_type()) {
+ set_primitive_base_type(type, base_type);
}
- kindstr = "type";
+ goto finish_type;
+ }
+
+ case tpo_struct: {
+ ident *id = read_ident_null(env);
+ type = new_type_struct(id);
+ set_type_size_bytes(type, size);
+ goto finish_type;
+ }
+
+ case tpo_union: {
+ ident *id = read_ident_null(env);
+ type = new_type_union(id);
+ set_type_size_bytes(type, size);
+ goto finish_type;
+ }
+
+ case tpo_none:
+ case tpo_code:
+ case tpo_unknown:
+ 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);
- set_type_visibility(type, vis);
+ type->flags = flags;
- if(state == layout_fixed)
+ if (state == layout_fixed)
ARR_APP1(ir_type *, env->fixedtypes, type);
set_id(env, typenr, type);
- printf("Insert %s %s %ld\n", kindstr, name, typenr);
+}
+
+static void read_unknown_entity(read_env_t *env)
+{
+ long entnr = read_long(env);
+ ir_entity *entity = get_unknown_entity();
+ set_id(env, entnr, entity);
}
/** Reads an entity description and remembers it by its id. */
-static void import_entity(io_env_t *env)
-{
- char buf[1024], buf2[1024];
- long entnr = read_long(env);
- const char *name = read_qstr_to(env, buf, sizeof(buf));
- const char *ld_name = read_qstr_to(env, buf2, sizeof(buf2));
- long typenr = read_long(env);
- long ownertypenr = read_long(env);
-
- ir_type *type = get_type(env, typenr);
- ir_type *ownertype = !ownertypenr ? get_glob_type() : get_type(env, ownertypenr);
- ir_entity *entity = new_entity(ownertype, new_id_from_str(name), type);
-
- if(*ld_name) set_entity_ld_ident(entity, new_id_from_str(ld_name));
- set_entity_offset (entity, (int) read_long(env));
- set_entity_offset_bits_remainder(entity, (unsigned char) read_long(env));
- set_entity_allocation (entity, read_allocation(env));
- set_entity_visibility (entity, read_visibility(env));
- set_entity_variability(entity, read_variability(env));
- set_entity_peculiarity(entity, read_peculiarity(env));
- set_entity_volatility (entity, read_volatility(env));
-
- if(get_entity_variability(entity) != variability_uninitialized
- && get_entity_visibility(entity) != visibility_external_allocated)
- {
- if(is_compound_entity(entity))
- {
- if(!strcmp(read_str_to(env, buf2, sizeof(buf2)), "initializer"))
- {
- set_entity_initializer(entity, read_initializer(env));
- }
- else
- {
- int i, n = (int) read_long(env);
- 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);
- }
- }
+static void read_entity(read_env_t *env, ir_entity_kind kind)
+{
+ long entnr = read_long(env);
+ ident *name = NULL;
+ ident *ld_name = NULL;
+ ir_visibility visibility = ir_visibility_external;
+ ir_linkage linkage = IR_LINKAGE_DEFAULT;
+ ir_type *owner = NULL;
+ ir_entity *entity = NULL;
+ int compiler_generated;
+ ir_volatility volatility;
+ const char *str;
+ ir_type *type;
+
+ if (kind != IR_ENTITY_LABEL && kind != IR_ENTITY_PARAMETER) {
+ name = read_ident(env);
+ ld_name = read_ident_null(env);
+ }
+
+ 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);
}
- else
- {
- ir_node *irn = get_node_or_dummy(env, read_long(env));
- set_atomic_ent_value(entity, irn);
+ 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);
}
+ 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;
+ }
+ case IR_ENTITY_UNKNOWN:
+ panic("read_entity with IR_ENTITY_UNKNOWN?");
+ }
+
+ set_entity_compiler_generated(entity, compiler_generated);
+ set_entity_volatility(entity, volatility);
+ set_entity_visibility(entity, visibility);
+ set_entity_linkage(entity, linkage);
+
+ if (owner != NULL && is_Array_type(owner)) {
+ set_array_element_entity(owner, entity);
}
set_id(env, entnr, entity);
- printf("Insert entity %s %ld\n", name, entnr);
}
/** Parses the whole type graph. */
-static int parse_typegraph(io_env_t *env)
+static void read_typegraph(read_env_t *env)
{
- const char *kind;
- keyword_t kwkind;
- lex_state_t oldstate;
+ ir_graph *old_irg = env->irg;
EXPECT('{');
- save_lex_state(env, &oldstate);
+ env->irg = get_const_code_irg();
- current_ir_graph = get_const_code_irg();
-
- // parse all types first
- while(1)
- {
- kind = read_str(env);
- if(kind[0] == '}' && !kind[1]) break;
+ /* parse all types first */
+ while (true) {
+ keyword_t kwkind;
+ skip_ws(env);
+ if (env->c == '}') {
+ read_c(env);
+ break;
+ }
- kwkind = (keyword_t) symbol(kind, tt_keyword);
- switch(kwkind)
- {
- case kw_type:
- case kw_frametype:
- case kw_valuetype:
- import_type(env, kwkind);
- break;
+ kwkind = read_keyword(env);
+ switch (kwkind) {
+ case kw_type:
+ read_type(env);
+ break;
- default:
- skip_to(env, '\n');
- break;
+ case kw_entity:
+ 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;
+ case kw_unknown:
+ read_unknown_entity(env);
+ break;
+ default:
+ parse_error(env, "type graph element not supported yet: %d\n", kwkind);
+ skip_to(env, '\n');
+ break;
}
}
+ env->irg = old_irg;
+}
+
+/**
+ * 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)
+{
+ 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;
+}
- // now parse rest
- restore_lex_state(env, &oldstate);
+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*);
+}
- while(1)
- {
- kind = read_str(env);
- if(kind[0] == '}' && !kind[1]) break;
+static void read_preds_delayed(read_env_t *env, ir_node *node)
+{
+ int n_preds = 0;
+ delayed_pred_t *d;
- switch(symbol(kind, tt_keyword))
- {
- case kw_type:
- case kw_frametype:
- case kw_valuetype:
- skip_to(env, '\n');
- break;
+ expect_list_begin(env);
+ 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;
- case kw_entity:
- import_entity(env);
- break;
+ ARR_APP1(const delayed_pred_t*, env->delayed_preds, d);
+}
- default:
- printf("Type graph element not supported yet: \"%s\"\n", kind);
- skip_to(env, '\n');
- break;
- }
+static ir_node *read_ASM(read_env_t *env)
+{
+ 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);
+ ir_node *mem = read_node_ref(env);
+ op_pin_state pin_state;
+
+ ident *asm_text = read_ident(env);
+
+ expect_list_begin(env);
+ while (list_has_next(env)) {
+ ir_asm_constraint constraint;
+ constraint.pos = read_unsigned(env);
+ constraint.constraint = read_ident(env);
+ constraint.mode = read_mode_ref(env);
+ ARR_APP1(ir_asm_constraint, input_constraints, constraint);
+ }
+
+ expect_list_begin(env);
+ while (list_has_next(env)) {
+ ir_asm_constraint constraint;
+ constraint.pos = read_unsigned(env);
+ constraint.constraint = read_ident(env);
+ constraint.mode = read_mode_ref(env);
+ ARR_APP1(ir_asm_constraint, output_constraints, constraint);
+ }
+
+ expect_list_begin(env);
+ while (list_has_next(env)) {
+ ident *clobber = read_ident(env);
+ ARR_APP1(ident*, clobbers, clobber);
}
- return 1;
+
+ pin_state = read_pin_state(env);
+
+ n_in = read_preds(env);
+ in = (ir_node**)obstack_finish(&env->preds_obst);
+
+ 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, mem, 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;
+}
+
+static ir_node *read_Phi(read_env_t *env)
+{
+ 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;
}
-static int read_node_header(io_env_t *env, long *nodenr, long **preds, const char **nodename)
+static ir_node *read_Block(read_env_t *env)
{
- int numpreds;
- *nodename = read_str(env);
- if((*nodename)[0] == '}' && !(*nodename)[1]) return -1; // end-of-graph
+ ir_node *res = new_r_Block(env->irg, 0, NULL);
+ read_preds_delayed(env, res);
+ return res;
+}
- *nodenr = read_long(env);
+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;
+}
- ARR_RESIZE(ir_node *, *preds, 0);
+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;
- EXPECT('[');
- for(numpreds = 0; !feof(env->file); numpreds++)
- {
- char *endptr;
- ARR_APP1(long, *preds, read_long2(env, &endptr));
- if(*endptr == ']') break;
- }
- return numpreds;
+ sym.entity_p = entity;
+ res = new_r_SymConst(env->irg, mode, sym, symconst_addr_ent);
+ return res;
}
-/** Parses an IRG. */
-static int parse_graph(io_env_t *env, ir_graph *irg)
+static ir_node *read_Anchor(read_env_t *env)
{
- long *preds = NEW_ARR_F(long, 16);
- ir_node **prednodes = NEW_ARR_F(ir_node *, 16);
- int i, numpreds, ret = 1;
- long nodenr;
- const char *nodename;
- ir_node *node, *newnode;
+ ir_node *res = new_r_Anchor(env->irg);
+ read_preds_delayed(env, res);
+ return res;
+}
- current_ir_graph = irg;
+typedef ir_node* read_node_func(read_env_t *env);
+static pmap *node_readers;
- EXPECT('{');
+static void register_node_reader(ident *ident, read_node_func* func)
+{
+ pmap_insert(node_readers, ident, (void*)func);
+}
- while(1)
- {
- numpreds = read_node_header(env, &nodenr, &preds, &nodename);
- if(numpreds == -1) break; // end-of-graph
- if(!numpreds)
- {
- printf("Node %s %ld is missing predecessors!", nodename, nodenr);
- ret = 0;
- break;
- }
+static ir_node *read_node(read_env_t *env)
+{
+ ident *id = read_symbol(env);
+ read_node_func *func = pmap_get(read_node_func, 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;
+}
- ARR_RESIZE(ir_node *, prednodes, numpreds);
- for(i = 0; i < numpreds - 1; i++)
- prednodes[i] = get_node_or_dummy(env, preds[i + 1]);
+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();
+}
- node = get_node_or_null(env, nodenr);
- newnode = NULL;
+static void read_graph(read_env_t *env, ir_graph *irg)
+{
+ size_t n_delayed_preds;
+ size_t i;
+ env->irg = irg;
- EXPECT('{');
+ env->delayed_preds = NEW_ARR_F(const delayed_pred_t*, 0);
- switch(symbol(nodename, tt_iro))
- {
- case iro_End:
- {
- ir_node *newendblock = get_node(env, preds[0]);
- newnode = get_irg_end(current_ir_graph);
- exchange(get_nodes_block(newnode), newendblock);
- for(i = 0; i < numpreds - 1; i++)
- add_irn_n(newnode, prednodes[i]);
- break;
- }
+ EXPECT('{');
+ while (true) {
+ skip_ws(env);
+ if (env->c == '}' || env->c == EOF) {
+ read_c(env);
+ break;
+ }
- case iro_Start:
- {
- ir_node *newstartblock = get_node(env, preds[0]);
- newnode = get_irg_start(current_ir_graph);
- exchange(get_nodes_block(newnode), newstartblock);
- break;
- }
+ read_node(env);
+ }
- case iro_Block:
- {
- if(preds[0] != nodenr)
- {
- printf("Invalid block: preds[0] != nodenr (%ld != %ld)\n",
- preds[0], nodenr);
- ret = 0;
- goto endloop;
- }
-
- newnode = new_Block(numpreds - 1, prednodes);
- break;
+ /* 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;
+ }
+ 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);
+ }
+ }
+next_delayed_pred: ;
+ }
+ DEL_ARR_F(env->delayed_preds);
+ env->delayed_preds = NULL;
+}
- case iro_Anchor:
- newnode = current_ir_graph->anchor;
- for(i = 0; i < numpreds - 1; i++)
- set_irn_n(newnode, i, prednodes[i]);
- set_irn_n(newnode, -1, get_node(env, preds[0]));
- break;
+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);
+ set_irg_frame_type(irg, frame);
+ read_graph(env, irg);
+ irg_finalize_cons(irg);
+ return irg;
+}
- case iro_SymConst:
- {
- long entnr = read_long(env);
- union symconst_symbol sym;
- sym.entity_p = get_entity(env, entnr);
- newnode = new_SymConst(mode_P, sym, symconst_addr_ent);
- break;
- }
+static void read_modes(read_env_t *env)
+{
+ EXPECT('{');
- #include "gen_irio_import.inl"
+ while (true) {
+ keyword_t kwkind;
- default:
- goto notsupported;
+ skip_ws(env);
+ if (env->c == '}' || env->c == EOF) {
+ read_c(env);
+ break;
}
- EXPECT('}');
-
- if(!newnode)
- {
-notsupported:
- panic("Node type not supported yet: %s in line %i:%i\n", nodename, env->line, env->col);
+ kwkind = read_keyword(env);
+ switch (kwkind) {
+ case kw_int_mode: {
+ const char *name = read_string(env);
+ ir_mode_arithmetic arith = read_mode_arithmetic(env);
+ int size = read_long(env);
+ int sign = read_long(env);
+ unsigned modulo_shift = read_long(env);
+ new_int_mode(name, arith, size, sign, modulo_shift);
+ break;
+ }
+ case kw_reference_mode: {
+ const char *name = read_string(env);
+ ir_mode_arithmetic arith = read_mode_arithmetic(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_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);
+ set_modeP_code(mode);
+ }
+ break;
+ }
+ case kw_float_mode: {
+ const char *name = read_string(env);
+ ir_mode_arithmetic arith = read_mode_arithmetic(env);
+ int exponent_size = read_long(env);
+ int mantissa_size = read_long(env);
+ new_float_mode(name, arith, exponent_size, mantissa_size);
+ break;
}
- if(node)
- exchange(node, newnode);
- /* Always update hash entry to avoid more uses of id nodes */
- set_id(env, nodenr, newnode);
- //printf("Insert %s %ld\n", nodename, nodenr);
+ default:
+ skip_to(env, '\n');
+ break;
+ }
}
-
-endloop:
- DEL_ARR_F(preds);
- DEL_ARR_F(prednodes);
-
- return ret;
}
-static int parse_modes(io_env_t *env)
+static void read_program(read_env_t *env)
{
- const char *kind;
- keyword_t kwkind;
-
EXPECT('{');
- while(1)
- {
- kind = read_str(env);
- if(kind[0] == '}' && !kind[1]) break;
-
- kwkind = (keyword_t) symbol(kind, tt_keyword);
- switch(kwkind)
- {
- case kw_mode:
- {
- const char *name = read_qstr(env);
- ir_mode_sort sort = (ir_mode_sort) read_long(env);
- int size = read_long(env);
- int sign = read_long(env);
- ir_mode_arithmetic arith = read_mode_arithmetic(env);
- unsigned modulo_shift = read_long(env);
- int vector_elems = read_long(env);
-
- ir_mode *mode = new_ir_mode(name, sort, size, sign, arith, modulo_shift);
-
- if(mode_is_reference(mode))
- {
- set_reference_mode_signed_eq(mode, read_mode(env));
- set_reference_mode_unsigned_eq(mode, read_mode(env));
- }
- break;
- }
+ while (true) {
+ keyword_t kwkind;
- default:
- skip_to(env, '\n');
- break;
+ skip_ws(env);
+ if (env->c == '}') {
+ read_c(env);
+ break;
+ }
+
+ 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_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');
}
}
}
-/** Imports an previously exported textual representation of an (maybe partial) irp */
-void ir_import(const char *filename)
+int ir_import(const char *filename)
{
- int oldoptimize = get_optimize();
- firm_verification_t oldver = get_node_verification_mode();
- io_env_t ioenv;
- io_env_t *env = &ioenv;
- int i, n;
+ FILE *file = fopen(filename, "rt");
+ int res;
+ if (file == NULL) {
+ perror(filename);
+ return 1;
+ }
+
+ res = ir_import_file(file, filename);
+ fclose(file);
+
+ return res;
+}
+int ir_import_file(FILE *input, const char *inputname)
+{
+ 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));
- env->idset = new_set(id_cmp, 128);
+ 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);
- env->file = fopen(filename, "rt");
- if(!env->file)
- {
- perror(filename);
- exit(1);
- }
+ /* read first character */
+ read_c(env);
+
+ /* if the first line starts with '#', it contains a comment. */
+ if (env->c == '#')
+ skip_to(env, '\n');
set_optimize(0);
- do_node_verification(FIRM_VERIFICATION_OFF);
- while(1)
- {
- const char *str = read_str(env);
- if(!*str) break;
- switch(symbol(str, tt_keyword))
- {
- case kw_modes:
- if(!parse_modes(env)) goto end;
- break;
+ while (true) {
+ keyword_t kw;
- case kw_typegraph:
- if(!parse_typegraph(env)) goto end;
- break;
+ skip_ws(env);
+ if (env->c == EOF)
+ break;
- case kw_irg:
- {
- ir_entity *irgent = get_entity(env, read_long(env));
- long valuetypeid;
- ir_graph *irg = new_ir_graph(irgent, 0);
- set_irg_frame_type(irg, get_type(env, read_long(env)));
- valuetypeid = read_long(env);
- if(valuetypeid != -1)
- set_method_value_param_type(get_entity_type(irgent),
- get_type(env, valuetypeid));
-
- if(!parse_graph(env, irg)) goto end;
- break;
- }
+ kw = read_keyword(env);
+ switch (kw) {
+ case kw_modes:
+ read_modes(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;
- break;
- }
+ case kw_typegraph:
+ read_typegraph(env);
+ break;
+
+ case kw_irg:
+ 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);
+ read_graph(env, constirg);
+ break;
+ }
+
+ case kw_program:
+ read_program(env);
+ break;
+
+ default: {
+ parse_error(env, "Unexpected keyword %d at toplevel\n", kw);
+ exit(1);
+ }
}
}
-end:
n = ARR_LEN(env->fixedtypes);
- for(i = 0; i < n; i++)
+ 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);
- fclose(env->file);
+ 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"