Commit bd092bd1 authored by Matthias Braun's avatar Matthias Braun
Browse files

irio: complete rewrite

This should fix all known bugs, make the code easier to read and more
robust.
parent fa526598
...@@ -35,43 +35,32 @@ ...@@ -35,43 +35,32 @@
/** /**
* Exports the whole irp to the given file in a textual form. * 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 * @param filename the name of the resulting file
* * @return 0 if no errors occured, other values in case of errors
* Exports all types, all ir graphs, and the constant graph.
*/ */
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* * 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); FIRM_API void ir_export_file(FILE *output);
/**
* 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);
/** /**
* Imports the data stored in the given file. * 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 * @param filename the name of the file
* * @returns 0 if no errors occured, other values in case of errors
* Imports any type graphs and ir graphs contained in the file.
*/ */
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* * 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" #include "end.h"
......
...@@ -53,12 +53,9 @@ typedef enum ir_mode_arithmetic { ...@@ -53,12 +53,9 @@ typedef enum ir_mode_arithmetic {
to ieee754 floating point standard. Only to ieee754 floating point standard. Only
legal for modes of sort float_number. */ legal for modes of sort float_number. */
irma_x86_extended_float, /**< x86 extended floatingpoint values */ irma_x86_extended_float, /**< x86 extended floatingpoint values */
irma_max irma_last = irma_x86_extended_float,
} ir_mode_arithmetic; } 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. * Creates a new mode.
* *
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
/** /**
* @file * @file
* @brief Write textual representation of firm to file. * @brief Write textual representation of firm to file.
* @author Moritz Kroll * @author Moritz Kroll, Matthias Braun
*/ */
#include "config.h" #include "config.h"
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "irprog.h" #include "irprog.h"
#include "irgraph_t.h" #include "irgraph_t.h"
#include "irprintf.h" #include "irprintf.h"
#include "ircons.h" #include "ircons_t.h"
#include "irgmod.h" #include "irgmod.h"
#include "irflag_t.h" #include "irflag_t.h"
#include "irgwalk.h" #include "irgwalk.h"
...@@ -43,67 +43,94 @@ ...@@ -43,67 +43,94 @@
#include "array.h" #include "array.h"
#include "error.h" #include "error.h"
#include "typerep.h" #include "typerep.h"
#include "adt/set.h" #include "set.h"
#include "adt/obst.h" #include "obst.h"
#include "pmap.h"
#include "pdeq.h"
#define SYMERROR ((unsigned) ~0) #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 */ int c; /**< currently read char */
FILE *file; FILE *file;
set *idset; /**< id_entry set, which maps from file ids to new Firm elements */
int ignoreblocks;
const char *inputname; const char *inputname;
int line; unsigned line;
ir_graph *irg;
set *idset; /**< id_entry set, which maps from file ids to
new Firm elements */
ir_type **fixedtypes; ir_type **fixedtypes;
bool read_errors;
struct obstack obst; struct obstack obst;
ir_graph *irg; struct obstack preds_obst;
} io_env_t; 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_align,
tt_allocation, tt_builtin_kind,
tt_builtin,
tt_cond_jmp_predicate, tt_cond_jmp_predicate,
tt_initializer, tt_initializer,
tt_iro, tt_irg_inline_property,
tt_keyword, tt_keyword,
tt_linkage,
tt_mode_arithmetic, tt_mode_arithmetic,
tt_pin_state, tt_pin_state,
tt_segment,
tt_throws,
tt_tpo, tt_tpo,
tt_type_state, tt_type_state,
tt_visibility,
tt_volatility, tt_volatility,
tt_linkage, tt_where_alloc,
tt_segment,
tt_visibility
} typetag_t; } typetag_t;
typedef enum keyword_t typedef enum keyword_t {
{ kw_asm,
kw_compound_member,
kw_constirg, kw_constirg,
kw_entity, kw_entity,
kw_irg,
kw_int_mode,
kw_reference_mode,
kw_float_mode, kw_float_mode,
kw_int_mode,
kw_irg,
kw_label,
kw_method,
kw_modes, kw_modes,
kw_parameter,
kw_program,
kw_reference_mode,
kw_segment_type,
kw_type, kw_type,
kw_typegraph, kw_typegraph,
kw_program,
kw_segment_type
} keyword_t; } keyword_t;
typedef struct symbol_t typedef struct symbol_t {
{
const char *str; /**< The name of this symbol. */ const char *str; /**< The name of this symbol. */
typetag_t typetag; /**< The type tag of this symbol. */ typetag_t typetag; /**< The type tag of this symbol. */
unsigned code; /**< The value of this symbol. */ unsigned code; /**< The value of this symbol. */
} symbol_t; } symbol_t;
typedef struct id_entry typedef struct id_entry {
{
long id; long id;
void *elem; void *elem;
} id_entry; } id_entry;
...@@ -134,10 +161,10 @@ static int id_cmp(const void *elt, const void *key, size_t size) ...@@ -134,10 +161,10 @@ static int id_cmp(const void *elt, const void *key, size_t size)
} }
static void __attribute__((format(printf, 2, 3))) 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; va_list ap;
int line = env->line; unsigned line = env->line;
/* workaround read_c "feature" that a '\n' triggers the line++ /* workaround read_c "feature" that a '\n' triggers the line++
* instead of the character after the '\n' */ * instead of the character after the '\n' */
...@@ -145,7 +172,11 @@ parse_error(io_env_t *env, const char *fmt, ...) ...@@ -145,7 +172,11 @@ parse_error(io_env_t *env, const char *fmt, ...)
line--; 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); va_start(ap, fmt);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
...@@ -197,37 +228,43 @@ static void symtbl_init(void) ...@@ -197,37 +228,43 @@ static void symtbl_init(void)
INSERT(tt_visibility, "default", ir_visibility_default); INSERT(tt_visibility, "default", ir_visibility_default);
INSERT(tt_visibility, "private", ir_visibility_private); 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(constirg);
INSERTKEYWORD(entity); INSERTKEYWORD(entity);
INSERTKEYWORD(irg);
INSERTKEYWORD(int_mode);
INSERTKEYWORD(float_mode); INSERTKEYWORD(float_mode);
INSERTKEYWORD(reference_mode); INSERTKEYWORD(int_mode);
INSERTKEYWORD(irg);
INSERTKEYWORD(label);
INSERTKEYWORD(method);
INSERTKEYWORD(modes); INSERTKEYWORD(modes);
INSERTKEYWORD(type); INSERTKEYWORD(parameter);
INSERTKEYWORD(typegraph);
INSERTKEYWORD(program); INSERTKEYWORD(program);
INSERTKEYWORD(reference_mode);
INSERTKEYWORD(segment_type); INSERTKEYWORD(segment_type);
INSERTKEYWORD(type);
#include "gen_irio_lex.inl" INSERTKEYWORD(typegraph);
INSERTENUM(tt_align, align_non_aligned); INSERTENUM(tt_align, align_non_aligned);
INSERTENUM(tt_align, align_is_aligned); INSERTENUM(tt_align, align_is_aligned);
INSERTENUM(tt_builtin, ir_bk_trap); INSERTENUM(tt_builtin_kind, ir_bk_trap);
INSERTENUM(tt_builtin, ir_bk_debugbreak); INSERTENUM(tt_builtin_kind, ir_bk_debugbreak);
INSERTENUM(tt_builtin, ir_bk_return_address); INSERTENUM(tt_builtin_kind, ir_bk_return_address);
INSERTENUM(tt_builtin, ir_bk_frame_address); INSERTENUM(tt_builtin_kind, ir_bk_frame_address);
INSERTENUM(tt_builtin, ir_bk_prefetch); INSERTENUM(tt_builtin_kind, ir_bk_prefetch);
INSERTENUM(tt_builtin, ir_bk_ffs); INSERTENUM(tt_builtin_kind, ir_bk_ffs);
INSERTENUM(tt_builtin, ir_bk_clz); INSERTENUM(tt_builtin_kind, ir_bk_clz);
INSERTENUM(tt_builtin, ir_bk_ctz); INSERTENUM(tt_builtin_kind, ir_bk_ctz);
INSERTENUM(tt_builtin, ir_bk_popcount); INSERTENUM(tt_builtin_kind, ir_bk_popcount);
INSERTENUM(tt_builtin, ir_bk_parity); INSERTENUM(tt_builtin_kind, ir_bk_parity);
INSERTENUM(tt_builtin, ir_bk_bswap); INSERTENUM(tt_builtin_kind, ir_bk_bswap);
INSERTENUM(tt_builtin, ir_bk_inport); INSERTENUM(tt_builtin_kind, ir_bk_inport);
INSERTENUM(tt_builtin, ir_bk_outport); INSERTENUM(tt_builtin_kind, ir_bk_outport);
INSERTENUM(tt_builtin, ir_bk_inner_trampoline); 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_NONE);
INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_TRUE); INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_TRUE);
...@@ -238,10 +275,17 @@ static void symtbl_init(void) ...@@ -238,10 +275,17 @@ static void symtbl_init(void)
INSERTENUM(tt_initializer, IR_INITIALIZER_NULL); INSERTENUM(tt_initializer, IR_INITIALIZER_NULL);
INSERTENUM(tt_initializer, IR_INITIALIZER_COMPOUND); INSERTENUM(tt_initializer, IR_INITIALIZER_COMPOUND);
INSERTENUM(tt_mode_arithmetic, irma_uninitialized); INSERT(tt_mode_arithmetic, "uninitialized", irma_uninitialized);
INSERTENUM(tt_mode_arithmetic, irma_none); INSERT(tt_mode_arithmetic, "none", irma_none);
INSERTENUM(tt_mode_arithmetic, irma_twos_complement); INSERT(tt_mode_arithmetic, "twos_complement", irma_twos_complement);
INSERTENUM(tt_mode_arithmetic, irma_ieee754); 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_floats);
INSERTENUM(tt_pin_state, op_pin_state_pinned); INSERTENUM(tt_pin_state, op_pin_state_pinned);
...@@ -254,6 +298,9 @@ static void symtbl_init(void) ...@@ -254,6 +298,9 @@ static void symtbl_init(void)
INSERTENUM(tt_volatility, volatility_non_volatile); INSERTENUM(tt_volatility, volatility_non_volatile);
INSERTENUM(tt_volatility, volatility_is_volatile); INSERTENUM(tt_volatility, volatility_is_volatile);
INSERTENUM(tt_where_alloc, stack_alloc);
INSERTENUM(tt_where_alloc, heap_alloc);
#undef INSERTKEYWORD #undef INSERTKEYWORD
#undef INSERTENUM #undef INSERTENUM
#undef INSERT #undef INSERT
...@@ -267,7 +314,7 @@ static const char *get_segment_name(ir_segment_t segment) ...@@ -267,7 +314,7 @@ static const char *get_segment_name(ir_segment_t segment)
case IR_SEGMENT_CONSTRUCTORS: return "constructors"; case IR_SEGMENT_CONSTRUCTORS: return "constructors";
case IR_SEGMENT_DESTRUCTORS: return "destructors"; case IR_SEGMENT_DESTRUCTORS: return "destructors";
} }
return "INVALID_SEGMENT"; panic("INVALID_SEGMENT");
} }
static const char *get_visibility_name(ir_visibility visibility) static const char *get_visibility_name(ir_visibility visibility)
...@@ -278,7 +325,31 @@ 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_default: return "default";
case ir_visibility_private: return "private"; 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. */ /** 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) ...@@ -293,49 +364,51 @@ static unsigned symbol(const char *str, typetag_t typetag)
return entry ? entry->code : SYMERROR; 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; fprintf(env->file, "%ld ", value);
key.id = id;
entry = (id_entry*)set_find(env->idset, &key, sizeof(key), (unsigned) id);
return entry ? entry->elem : NULL;
} }
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; fprintf(env->file, "%d ", value);
key.id = id;
key.elem = elem;
set_insert(env->idset, &key, sizeof(key), (unsigned) id);
} }
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)); 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)
{ {
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)); 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; const char *c;
fputc('"', env->file); fputc('"', env->file);
...@@ -355,15 +428,15 @@ static void write_string(io_env_t *env, const char *string) ...@@ -355,15 +428,15 @@ static void write_string(io_env_t *env, const char *string)
} }
} }
fputc('"', env->file); 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)); 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) { if (id == NULL) {
fputs("NULL ", env->file); fputs("NULL ", env->file);
...@@ -372,50 +445,87 @@ static void write_ident_null(io_env_t *env, ident *id) ...@@ -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)); 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)
{ {
write_mode_ref(env, get_tarval_mode(tv));
if (tv == tarval_bad) {
write_symbol(env, "bad");
} else {
char buf[1024]; char buf[1024];
write_mode(env, get_tarval_mode(tv));
tarval_snprintf(buf, sizeof(buf), tv); tarval_snprintf(buf, sizeof(buf), tv);
fputs(buf, env->file); fputs(buf, env->file);
fputc(' ', 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); fputs(get_align_name(align), env->file);
fputc(' ', env->file); fputc(' ', env->file);
} }