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 @@
/**
* Exports the whole irp to the given file in a textual form.
* Exports all types, all ir graphs, and the constant graph.
*
* @param filename the name of the resulting file
*
* Exports all types, all ir graphs, and the constant graph.
* @return 0 if no errors occured, other values in case of errors
*/
FIRM_API void ir_export(const char *filename);
FIRM_API int ir_export(const char *filename);
/**
* same as ir_export but writes to a FILE*
* @note As with any FILE* errors are indicated by ferror(output)
*/
FIRM_API void ir_export_file(FILE *output, const char *outputname);
/**
* Write the given ir graph to a stream in a textual format
*
* @param irg the ir graph
* @param output output stream the irg is written to
* @param outputname a name for the output stream (used for error messages)
*
* Exports the type graph used by the given graph and the graph itself.
*/
FIRM_API void ir_export_irg(ir_graph *irg, FILE *output,
const char *outputname);
FIRM_API void ir_export_file(FILE *output);
/**
* Imports the data stored in the given file.
* Imports any type graphs and ir graphs contained in the file.
*
* @param filename the name of the file
*
* Imports any type graphs and ir graphs contained in the file.
* @returns 0 if no errors occured, other values in case of errors
*/
FIRM_API void ir_import(const char *filename);
FIRM_API int ir_import(const char *filename);
/**
* same as ir_import but imports from a FILE*
*/
FIRM_API void ir_import_file(FILE *input, const char *inputname);
FIRM_API int ir_import_file(FILE *input, const char *inputname);
#include "end.h"
......
......@@ -53,12 +53,9 @@ typedef enum ir_mode_arithmetic {
to ieee754 floating point standard. Only
legal for modes of sort float_number. */
irma_x86_extended_float, /**< x86 extended floatingpoint values */
irma_max
irma_last = irma_x86_extended_float,
} ir_mode_arithmetic;
/** Returns the name of the arithmetic type. */
FIRM_API const char *get_mode_arithmetic_name(ir_mode_arithmetic ari);
/**
* Creates a new mode.
*
......
......@@ -20,7 +20,7 @@
/**
* @file
* @brief Write textual representation of firm to file.
* @author Moritz Kroll
* @author Moritz Kroll, Matthias Braun
*/
#include "config.h"
......@@ -35,7 +35,7 @@
#include "irprog.h"
#include "irgraph_t.h"
#include "irprintf.h"
#include "ircons.h"
#include "ircons_t.h"
#include "irgmod.h"
#include "irflag_t.h"
#include "irgwalk.h"
......@@ -43,67 +43,94 @@
#include "array.h"
#include "error.h"
#include "typerep.h"
#include "adt/set.h"
#include "adt/obst.h"
#include "set.h"
#include "obst.h"
#include "pmap.h"
#include "pdeq.h"
#define SYMERROR ((unsigned) ~0)
typedef struct io_env_t
{
int c; /**< currently read char */
FILE *file;
set *idset; /**< id_entry set, which maps from file ids to new Firm elements */
int ignoreblocks;
const char *inputname;
int line;
ir_type **fixedtypes;
static void register_generated_node_readers(void);
static void register_generated_node_writers(void);
typedef struct delayed_initializer_t {
ir_initializer_t *initializer;
long node_nr;
} delayed_initializer_t;
typedef struct delayed_pred_t {
ir_node *node;
int n_preds;
long preds[];
} delayed_pred_t;
typedef struct read_env_t {
int c; /**< currently read char */
FILE *file;
const char *inputname;
unsigned line;
ir_graph *irg;
set *idset; /**< id_entry set, which maps from file ids to
new Firm elements */
ir_type **fixedtypes;
bool read_errors;
struct obstack obst;
ir_graph *irg;
} io_env_t;
struct obstack preds_obst;
delayed_initializer_t *delayed_initializers;
const delayed_pred_t **delayed_preds;
} read_env_t;
typedef enum typetag_t
{
typedef struct write_env_t {
FILE *file;
pdeq *write_queue;
} write_env_t;
typedef enum typetag_t {
tt_align,
tt_allocation,
tt_builtin,
tt_builtin_kind,
tt_cond_jmp_predicate,
tt_initializer,
tt_iro,
tt_irg_inline_property,
tt_keyword,
tt_linkage,
tt_mode_arithmetic,
tt_pin_state,
tt_segment,
tt_throws,
tt_tpo,
tt_type_state,
tt_visibility,
tt_volatility,
tt_linkage,
tt_segment,
tt_visibility
tt_where_alloc,
} typetag_t;
typedef enum keyword_t
{
typedef enum keyword_t {
kw_asm,
kw_compound_member,
kw_constirg,
kw_entity,
kw_irg,
kw_int_mode,
kw_reference_mode,
kw_float_mode,
kw_int_mode,
kw_irg,
kw_label,
kw_method,
kw_modes,
kw_parameter,
kw_program,
kw_reference_mode,
kw_segment_type,
kw_type,
kw_typegraph,
kw_program,
kw_segment_type
} keyword_t;
typedef struct symbol_t
{
typedef struct symbol_t {
const char *str; /**< The name of this symbol. */
typetag_t typetag; /**< The type tag of this symbol. */
unsigned code; /**< The value of this symbol. */
} symbol_t;
typedef struct id_entry
{
typedef struct id_entry {
long id;
void *elem;
} id_entry;
......@@ -134,10 +161,10 @@ static int id_cmp(const void *elt, const void *key, size_t size)
}
static void __attribute__((format(printf, 2, 3)))
parse_error(io_env_t *env, const char *fmt, ...)
parse_error(read_env_t *env, const char *fmt, ...)
{
va_list ap;
int line = env->line;
va_list ap;
unsigned line = env->line;
/* workaround read_c "feature" that a '\n' triggers the line++
* instead of the character after the '\n' */
......@@ -145,7 +172,11 @@ parse_error(io_env_t *env, const char *fmt, ...)
line--;
}
fprintf(stderr, "%s:%d: error ", env->inputname, line);
fprintf(stderr, "%s:%u: error ", env->inputname, line);
env->read_errors = true;
/* let's hope firm doesn't die on further errors */
do_node_verification(0);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
......@@ -197,37 +228,43 @@ static void symtbl_init(void)
INSERT(tt_visibility, "default", ir_visibility_default);
INSERT(tt_visibility, "private", ir_visibility_private);
INSERT(tt_throws, "throw", true);
INSERT(tt_throws, "nothrow", false);
INSERTKEYWORD(asm);
INSERTKEYWORD(compound_member);
INSERTKEYWORD(constirg);
INSERTKEYWORD(entity);
INSERTKEYWORD(irg);
INSERTKEYWORD(int_mode);
INSERTKEYWORD(float_mode);
INSERTKEYWORD(reference_mode);
INSERTKEYWORD(int_mode);
INSERTKEYWORD(irg);
INSERTKEYWORD(label);
INSERTKEYWORD(method);
INSERTKEYWORD(modes);
INSERTKEYWORD(type);
INSERTKEYWORD(typegraph);
INSERTKEYWORD(parameter);
INSERTKEYWORD(program);
INSERTKEYWORD(reference_mode);
INSERTKEYWORD(segment_type);
#include "gen_irio_lex.inl"
INSERTKEYWORD(type);
INSERTKEYWORD(typegraph);
INSERTENUM(tt_align, align_non_aligned);
INSERTENUM(tt_align, align_is_aligned);
INSERTENUM(tt_builtin, ir_bk_trap);
INSERTENUM(tt_builtin, ir_bk_debugbreak);
INSERTENUM(tt_builtin, ir_bk_return_address);
INSERTENUM(tt_builtin, ir_bk_frame_address);
INSERTENUM(tt_builtin, ir_bk_prefetch);
INSERTENUM(tt_builtin, ir_bk_ffs);
INSERTENUM(tt_builtin, ir_bk_clz);
INSERTENUM(tt_builtin, ir_bk_ctz);
INSERTENUM(tt_builtin, ir_bk_popcount);
INSERTENUM(tt_builtin, ir_bk_parity);
INSERTENUM(tt_builtin, ir_bk_bswap);
INSERTENUM(tt_builtin, ir_bk_inport);
INSERTENUM(tt_builtin, ir_bk_outport);
INSERTENUM(tt_builtin, ir_bk_inner_trampoline);
INSERTENUM(tt_builtin_kind, ir_bk_trap);
INSERTENUM(tt_builtin_kind, ir_bk_debugbreak);
INSERTENUM(tt_builtin_kind, ir_bk_return_address);
INSERTENUM(tt_builtin_kind, ir_bk_frame_address);
INSERTENUM(tt_builtin_kind, ir_bk_prefetch);
INSERTENUM(tt_builtin_kind, ir_bk_ffs);
INSERTENUM(tt_builtin_kind, ir_bk_clz);
INSERTENUM(tt_builtin_kind, ir_bk_ctz);
INSERTENUM(tt_builtin_kind, ir_bk_popcount);
INSERTENUM(tt_builtin_kind, ir_bk_parity);
INSERTENUM(tt_builtin_kind, ir_bk_bswap);
INSERTENUM(tt_builtin_kind, ir_bk_inport);
INSERTENUM(tt_builtin_kind, ir_bk_outport);
INSERTENUM(tt_builtin_kind, ir_bk_inner_trampoline);
INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_NONE);
INSERTENUM(tt_cond_jmp_predicate, COND_JMP_PRED_TRUE);
......@@ -238,10 +275,17 @@ static void symtbl_init(void)
INSERTENUM(tt_initializer, IR_INITIALIZER_NULL);
INSERTENUM(tt_initializer, IR_INITIALIZER_COMPOUND);
INSERTENUM(tt_mode_arithmetic, irma_uninitialized);
INSERTENUM(tt_mode_arithmetic, irma_none);
INSERTENUM(tt_mode_arithmetic, irma_twos_complement);
INSERTENUM(tt_mode_arithmetic, irma_ieee754);
INSERT(tt_mode_arithmetic, "uninitialized", irma_uninitialized);
INSERT(tt_mode_arithmetic, "none", irma_none);
INSERT(tt_mode_arithmetic, "twos_complement", irma_twos_complement);
INSERT(tt_mode_arithmetic, "ieee754", irma_ieee754);
INSERT(tt_mode_arithmetic, "x86_extended_float", irma_x86_extended_float);
INSERT(tt_irg_inline_property, "any", irg_inline_any);
INSERT(tt_irg_inline_property, "recommended", irg_inline_recomended);
INSERT(tt_irg_inline_property, "forbidden", irg_inline_forbidden);
INSERT(tt_irg_inline_property, "forced", irg_inline_forced);
INSERT(tt_irg_inline_property, "forced_no_body", irg_inline_forced_no_body);
INSERTENUM(tt_pin_state, op_pin_state_floats);
INSERTENUM(tt_pin_state, op_pin_state_pinned);
......@@ -254,6 +298,9 @@ static void symtbl_init(void)
INSERTENUM(tt_volatility, volatility_non_volatile);
INSERTENUM(tt_volatility, volatility_is_volatile);
INSERTENUM(tt_where_alloc, stack_alloc);
INSERTENUM(tt_where_alloc, heap_alloc);
#undef INSERTKEYWORD
#undef INSERTENUM
#undef INSERT
......@@ -267,7 +314,7 @@ static const char *get_segment_name(ir_segment_t segment)
case IR_SEGMENT_CONSTRUCTORS: return "constructors";
case IR_SEGMENT_DESTRUCTORS: return "destructors";
}
return "INVALID_SEGMENT";
panic("INVALID_SEGMENT");
}
static const char *get_visibility_name(ir_visibility visibility)
......@@ -278,7 +325,31 @@ static const char *get_visibility_name(ir_visibility visibility)
case ir_visibility_default: return "default";
case ir_visibility_private: return "private";
}
return "INVALID_VISIBILITY";
panic("INVALID_VISIBILITY");
}
static const char *get_mode_arithmetic_name(ir_mode_arithmetic arithmetic)
{
switch (arithmetic) {
case irma_uninitialized: return "uninitialized";
case irma_none: return "none";
case irma_twos_complement: return "twos_complement";
case irma_ieee754: return "ieee754";
case irma_x86_extended_float: return "x86_extended_float";
}
panic("invalid mode_arithmetic");
}
static const char *get_irg_inline_property_name(irg_inline_property prop)
{
switch (prop) {
case irg_inline_any: return "any";
case irg_inline_recomended: return "recommended";
case irg_inline_forbidden: return "forbidden";
case irg_inline_forced: return "forced";
case irg_inline_forced_no_body: return "forced_no_body";
}
panic("invalid irg_inline_property");
}
/** Returns the according symbol value for the given string and tag, or SYMERROR if none was found. */
......@@ -293,49 +364,51 @@ static unsigned symbol(const char *str, typetag_t typetag)
return entry ? entry->code : SYMERROR;
}
static void *get_id(io_env_t *env, long id)
static void write_long(write_env_t *env, long value)
{
id_entry key, *entry;
key.id = id;
entry = (id_entry*)set_find(env->idset, &key, sizeof(key), (unsigned) id);
return entry ? entry->elem : NULL;
fprintf(env->file, "%ld ", value);
}
static void set_id(io_env_t *env, long id, void *elem)
static void write_int(write_env_t *env, int value)
{
id_entry key;
key.id = id;
key.elem = elem;
set_insert(env->idset, &key, sizeof(key), (unsigned) id);
fprintf(env->file, "%d ", value);
}
static void write_long(io_env_t *env, long value)
static void write_unsigned(write_env_t *env, unsigned value)
{
fprintf(env->file, "%ld ", value);
fprintf(env->file, "%u ", value);
}
static void write_int(io_env_t *env, int value)
static void write_size_t(write_env_t *env, size_t value)
{
fprintf(env->file, "%d ", value);
ir_fprintf(env->file, "%zu ", value);
}
static void write_unsigned(io_env_t *env, unsigned value)
static void write_symbol(write_env_t *env, const char *symbol)
{
fprintf(env->file, "%u ", value);
fputs(symbol, env->file);
fputc(' ', env->file);
}
static void write_entity_ref(io_env_t *env, ir_entity *entity)
static void write_entity_ref(write_env_t *env, ir_entity *entity)
{
write_long(env, get_entity_nr(entity));
}
static void write_type_ref(io_env_t *env, ir_type *type)
static void write_type_ref(write_env_t *env, ir_type *type)
{
write_long(env, get_type_nr(type));
if (type == firm_unknown_type) {
write_symbol(env, "unknown");
} else if (type == firm_none_type) {
write_symbol(env, "none");
} else if (type == firm_code_type) {
write_symbol(env, "code");
} else {
write_long(env, get_type_nr(type));
}
}
static void write_string(io_env_t *env, const char *string)
static void write_string(write_env_t *env, const char *string)
{
const char *c;
fputc('"', env->file);
......@@ -355,15 +428,15 @@ static void write_string(io_env_t *env, const char *string)
}
}
fputc('"', env->file);
fputc(' ', env->file);
}
static void write_ident(io_env_t *env, ident *id)
static void write_ident(write_env_t *env, ident *id)
{
write_string(env, get_id_str(id));
fputc(' ', env->file);
}
static void write_ident_null(io_env_t *env, ident *id)
static void write_ident_null(write_env_t *env, ident *id)
{
if (id == NULL) {
fputs("NULL ", env->file);
......@@ -372,50 +445,87 @@ static void write_ident_null(io_env_t *env, ident *id)
}
}
static void write_mode(io_env_t *env, ir_mode *mode)
static void write_mode_ref(write_env_t *env, ir_mode *mode)
{
write_string(env, get_mode_name(mode));
fputc(' ', env->file);
}
static void write_tarval(io_env_t *env, ir_tarval *tv)
static void write_tarval(write_env_t *env, ir_tarval *tv)
{
char buf[1024];
write_mode(env, get_tarval_mode(tv));
tarval_snprintf(buf, sizeof(buf), tv);
fputs(buf, env->file);
fputc(' ', env->file);
write_mode_ref(env, get_tarval_mode(tv));
if (tv == tarval_bad) {
write_symbol(env, "bad");
} else {
char buf[1024];
tarval_snprintf(buf, sizeof(buf), tv);
fputs(buf, env->file);
fputc(' ', env->file);
}
}
static void write_align(io_env_t *env, ir_align align)
static void write_align(write_env_t *env, ir_align align)
{
fputs(get_align_name(align), env->file);
fputc(' ', env->file);
}
static void write_builtin_kind(io_env_t *env, ir_node *irn)
static void write_builtin_kind(write_env_t *env, const ir_node *node)
{
fputs(get_builtin_kind_name(get_Builtin_kind(irn)), env->file);
fputs(get_builtin_kind_name(get_Builtin_kind(node)), env->file);
fputc(' ', env->file);
}
static void write_cond_jmp_predicate(io_env_t *env, ir_node *irn)
static void write_cond_jmp_predicate(write_env_t *env, const ir_node *node)
{
fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(irn)), env->file);
fputs(get_cond_jmp_predicate_name(get_Cond_jmp_pred(node)), env->file);
fputc(' ', env->file);
}
static void write_list_begin(io_env_t *env)
static void write_relation(write_env_t *env, ir_relation relation)
{
write_long(env, (long)relation);
}
static void write_where_alloc(write_env_t *env, ir_where_alloc where_alloc)
{
switch (where_alloc) {
case stack_alloc: write_symbol(env, "stack_alloc"); return;
case heap_alloc: write_symbol(env, "heap_alloc"); return;
}
panic("invalid where_alloc value");
}
static void write_throws(write_env_t *env, bool throws)
{
write_symbol(env, throws ? "throw" : "nothrow");
}
static void write_list_begin(write_env_t *env)
{
fputs("[", env->file);
}
static void write_list_end(io_env_t *env)
static void write_list_end(write_env_t *env)
{
fputs("] ", env->file);
}
static void write_initializer(io_env_t *env, ir_initializer_t *ini)
static void write_scope_begin(write_env_t *env)
{
fputs("{\n", env->file);
}
static void write_scope_end(write_env_t *env)
{
fputs("}\n\n", env->file);
}
static void write_node_ref(write_env_t *env, const ir_node *node)
{
write_long(env, get_irn_node_nr(node));
}
static void write_initializer(write_env_t *env, ir_initializer_t *ini)
{
FILE *f = env->file;
ir_initializer_kind_t ini_kind = get_initializer_kind(ini);
......@@ -425,273 +535,356 @@ static void write_initializer(io_env_t *env, ir_initializer_t *ini)
switch (ini_kind) {
case IR_INITIALIZER_CONST:
write_long(env, get_irn_node_nr(get_initializer_const_value(ini)));
break;
write_node_ref(env, get_initializer_const_value(ini));
return;
case IR_INITIALIZER_TARVAL:
write_tarval(env, get_initializer_tarval_value(ini));
break;
return;
case IR_INITIALIZER_NULL:
break;
return;
case IR_INITIALIZER_COMPOUND: {
size_t i, n = get_initializer_compound_n_entries(ini);
ir_fprintf(f, "%zu ", n);
write_size_t(env, n);
for (i = 0; i < n; ++i)
write_initializer(env, get_initializer_compound_value(ini, i));
break;
return;
}
default:
panic("Unknown initializer kind");
}
panic("Unknown initializer kind");
}
static void write_pin_state(io_env_t *env, ir_node *irn)
static void write_pin_state(write_env_t *env, op_pin_state state)
{
fputs(get_op_pin_state_name(get_irn_pinned(irn)), env->file);
fputs(get_op_pin_state_name(state), env->file);
fputc(' ', env->file);
}
static void write_volatility(io_env_t *env, ir_volatility vol)
static void write_volatility(write_env_t *env, ir_volatility vol)
{
fputs(get_volatility_name(vol), env->file);
fputc(' ', env->file);
}
static void export_type_common(io_env_t *env, ir_type *tp)
static void write_inline_property(write_env_t *env, irg_inline_property prop)
{
fprintf(env->file, "\ttype %ld %s %u %u %s %u ",
get_type_nr(tp),
get_type_tpop_name(tp),
get_type_size_bytes(tp),
get_type_alignment_bytes(tp),
get_type_state_name(get_type_state(tp)),
tp->flags);