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.
* *
......
This diff is collapsed.
...@@ -46,20 +46,6 @@ static struct obstack modes; ...@@ -46,20 +46,6 @@ static struct obstack modes;
/** The list of all currently existing modes. */ /** The list of all currently existing modes. */
static ir_mode **mode_list; static ir_mode **mode_list;
const char *get_mode_arithmetic_name(ir_mode_arithmetic ari)
{
#define X(a) case a: return #a
switch (ari) {
X(irma_uninitialized);
X(irma_none);
X(irma_twos_complement);
X(irma_ieee754);
X(irma_x86_extended_float);
default: return "<unknown>";
}
#undef X
}
static bool modes_are_equal(const ir_mode *m, const ir_mode *n) static bool modes_are_equal(const ir_mode *m, const ir_mode *n)
{ {
return m->sort == n->sort && return m->sort == n->sort &&
......
...@@ -17,18 +17,13 @@ def warning(msg): ...@@ -17,18 +17,13 @@ def warning(msg):
def format_args(arglist): def format_args(arglist):
return "\n".join(arglist) return "\n".join(arglist)
def format_ifnset(string, node, key):
if hasattr(node, key):
return ""
return string
def format_block(node): def format_block(node):
if hasattr(node, "knownBlock"): if hasattr(node, "knownBlock"):
if hasattr(node, "knownGraph"): if hasattr(node, "knownGraph"):
return "" return ""
return "irg" return "env->irg"
else: else:
return "preds[0]" return "block"
def format_arguments(string): def format_arguments(string):
args = re.split('\s*\n\s*', string) args = re.split('\s*\n\s*', string)
...@@ -38,152 +33,245 @@ def format_arguments(string): ...@@ -38,152 +33,245 @@ def format_arguments(string):
args = args[:-1] args = args[:-1]
return ", ".join(args) return ", ".join(args)
def filter_isnot(list, flag):
return filter(lambda x: not hasattr(x, flag), list)
def filter_notset(list, flag):
return filter(lambda x: not getattr(x,flag), list)
def filter_hasnot(list, flag):
return filter(lambda x: flag not in x, list)
env = Environment() env = Environment()
env.filters['args'] = format_args env.filters['args'] = format_args
env.filters['ifnset'] = format_ifnset
env.filters['block'] = format_block env.filters['block'] = format_block
env.filters['arguments'] = format_arguments env.filters['arguments'] = format_arguments
env.filters['isnot'] = filter_isnot
env.filters['notset'] = filter_notset
env.filters['hasnot'] = filter_hasnot
def get_io_type(type, attrname, node): def get_io_type(type, attrname, node):
if type == "ir_tarval*": if type == "ir_tarval*":
importcmd = "ir_tarval *%s = read_tv(env);" % attrname importcmd = "read_tarval(env)"
exportcmd = "write_tarval(env, %(val)s);"; exportcmd = "write_tarval(env, %(val)s);"
elif type == "ir_mode*": elif type == "ir_mode*":
importcmd = "ir_mode *%s = read_mode(env);" % attrname importcmd = "read_mode_ref(env)"
exportcmd = "write_mode(env, %(val)s);" exportcmd = "write_mode_ref(env, %(val)s);"
elif type == "ir_entity*": elif type == "ir_entity*":
importcmd = "ir_entity *%s = read_entity(env);" % attrname importcmd = "read_entity_ref(env)"
exportcmd = "write_entity_ref(env, %(val)s);" exportcmd = "write_entity_ref(env, %(val)s);"
elif type == "ir_type*": elif type == "ir_type*":
importcmd = "ir_type *%s = read_type(env);" % attrname importcmd = "read_type_ref(env)"
exportcmd = "write_type_ref(env, %(val)s);" exportcmd = "write_type_ref(env, %(val)s);"
elif type == "long" and node.name == "Proj": elif type == "long":
importcmd = "long %s = read_long(env);" % attrname importcmd = "read_long(env)"
exportcmd = "write_long(env, %(val)s);" exportcmd = "write_long(env, %(val)s);"
elif type == "ir_relation" or type == "ir_where_alloc": elif type == "ir_relation":
importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type) importcmd = "read_relation(env)"
exportcmd = "write_long(env, (long) %(val)s);" exportcmd = "write_relation(env, %(val)s);"
elif type == "ir_where_alloc":
importcmd = "read_where_alloc(env)"
exportcmd = "write_where_alloc(env, %(val)s);"
elif type == "ir_align": elif type == "ir_align":
importcmd = "ir_align %s = read_align(env);" % attrname importcmd = "read_align(env)"
exportcmd = "write_align(env, %(val)s);" exportcmd = "write_align(env, %(val)s);"
elif type == "ir_volatility": elif type == "ir_volatility":
importcmd = "ir_volatility %s = read_volatility(env);" % attrname importcmd = "read_volatility(env)"
exportcmd = "write_volatility(env, %(val)s);" exportcmd = "write_volatility(env, %(val)s);"
elif type == "ir_cons_flags": elif type == "ir_cons_flags":
importcmd = "ir_cons_flags %s = cons_none;" % attrname importcmd = "cons_none"
exportcmd = "" # can't really export cons_flags exportcmd = "" # can't really export cons_flags
elif type == "op_pin_state": elif type == "op_pin_state":
importcmd = "op_pin_state %s = read_pin_state(env);" % attrname importcmd = "read_pin_state(env)"
exportcmd = "write_pin_state(env, irn);" exportcmd = "write_pin_state(env, node);"
elif type == "ir_builtin_kind": elif type == "ir_builtin_kind":
importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname importcmd = "read_builtin_kind(env)"
exportcmd = "write_builtin_kind(env, irn);" exportcmd = "write_builtin_kind(env, node);"
elif type == "cond_kind": elif type == "cond_kind":
importcmd = "cond_kind %s = read_cond_kind(env);" % attrname importcmd = "read_cond_kind(env)"
exportcmd = "write_cond_kind(env, irn);" exportcmd = "write_cond_kind(env, node);"
elif type == "cond_jmp_predicate": elif type == "cond_jmp_predicate":
importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname importcmd = "read_cond_jmp_predicate(env)"
exportcmd = "write_cond_jmp_predicate(env, irn);" exportcmd = "write_cond_jmp_predicate(env, node);"
elif type == "int": elif type == "int":
importcmd = "int %s = read_int(env);" % attrname importcmd = "read_int(env)"
exportcmd = "write_int(env, %(val)s);" exportcmd = "write_int(env, %(val)s);"
elif type == "unsigned": elif type == "unsigned":
importcmd = "unsigned %s = read_unsigned(env);" % attrname importcmd = "read_unsigned(env)"
exportcmd = "write_unsigned(env, %(val)s);" exportcmd = "write_unsigned(env, %(val)s);"
elif type == "long": elif type == "long":
importcmd = "long %s = read_long(env);" % attrname importcmd = "read_long(env)"
exportcmd = "write_long(env, %(val)s);" exportcmd = "write_long(env, %(val)s);"
elif type == "ir_switch_table*":
importcmd = "read_switch_table(env)"
exportcmd = "write_switch_table(env, %(val)s);"
else: else:
warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type)) warning("cannot generate import/export for node %s: unsupported attribute type: %s" % (node.name, type))
importcmd = """// BAD: %s %s importcmd = "/* BAD: %s %s */ (%s)0" % (type, attrname, type)
%s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
exportcmd = "// BAD: %s" % type exportcmd = "// BAD: %s" % type
return (importcmd, exportcmd) return (importcmd, exportcmd)
def prepare_attr(node, attr): def prepare_attr(node, attr):
(importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node) (importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], node)
attr["importcmd"] = importcmd attr["importcmd"] = importcmd
attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (node.name, attr["name"])} attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(node)" % (node.name, attr["name"])}
def preprocess_node(node): def preprocess_node(node):
# dynamic pin state means, we have to im/export that
if is_dynamic_pinned(node):
newattr = dict(
name = "state",
type = "op_pin_state"
)
if hasattr(node, "pinned_init"):
newattr["init"] = node.pinned_init
node.attrs.append(newattr)
verify_node(node) verify_node(node)
if node.customSerializer:
return
# construct node arguments # construct node arguments
arguments = [ ] arguments = [ ]
initargs = [ ] extraattrs = [ ]
i = 1
for input in node.ins: for input in node.ins:
arguments.append("preds[%i]" % i) arguments.append("in_%s" % input[0])
i += 1
if node.arity == "variable" or node.arity == "dynamic": if node.arity == "variable" or node.arity == "dynamic":
arguments.append("numpreds - %i" % i) arguments.append("n_preds")
arguments.append("preds + %i" % i) arguments.append("preds")
if not hasattr(node, "mode"): if not hasattr(node, "mode"):
arguments.append("mode") arguments.append("mode")
for attr in node.attrs: for attr in node.attrs:
prepare_attr(node, attr) prepare_attr(node, attr)
if "init" in attr: if "to_flags" in attr:
if attr["type"] == "op_pin_state": node.constructorFlags = True
initfunc = "set_irn_pinned" attr['to_flags'] = attr['to_flags'] % (attr["name"])
else: elif "init" in attr:
initfunc = "set_" + node.name + "_" + attr["name"] extraattrs.append(attr)
initargs.append((attr["name"], initfunc))
else: else:
arguments.append(attr["name"]) arguments.append(attr["name"])
for arg in node.constructor_args: for arg in node.constructor_args:
prepare_attr(node, arg) if arg['type'] != "ir_cons_flags" and arg['name'] != "flags":
arguments.append(arg["name"]) error("only ir_cons_flags constructor arg supported in irio")
continue
node.constructorFlags = True
arguments.append("flags")
node.arguments = arguments node.arguments = arguments
node.initargs = initargs node.extraattrs = extraattrs
node.dynamic_pinned = is_dynamic_pinned(node)
export_attrs_template = env.from_string('''
case iro_{{node.name}}: io_template = env.from_string('''/* Warning: automatically generated code */
{{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}} {%- for node in nodes|notset('customSerializer') %}
{% for attr in node.attrs %}{{attr.exportcmd}} static ir_node *read_{{node.name}}(read_env_t *env)
{% endfor %} {
{% for attr in node.constructor_args %}{{attr.exportcmd}} {%- if not node.knownBlock %}
{% endfor %}break;''') ir_node *block = read_node_ref(env);
{%- endif %}
import_attrs_template = env.from_string(''' {%- for input in node.ins %}
case iro_{{node.name}}: { ir_node *in_{{input[0]}} = read_node_ref(env);
{{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}} {%- endfor %}
{% for attr in node.attrs %} {%- if not hasattr(node, "mode") %}
{{attr.importcmd}} ir_mode *mode = read_mode_ref(env);
{% endfor -%} {%- endif %}
{% for attr in node.constructor_args %} {%- for attr in node.attrs %}
{{attr.importcmd}} {{attr.type}} {{attr.name}} = {{attr.importcmd}};
{% endfor -%} {%- endfor %}
newnode = new_r_{{node.name}}( {%- if node.dynamic_pinned %}
{%- filter arguments %} op_pin_state pin_state = read_pin_state(env);
{%- endif %}
{%- if "fragile" in node.flags %}
bool throws = read_throws(env);
{%- endif %}
{%- if node.arity == "dynamic" or node.arity == "variable" %}
int n_preds = read_preds(env);
ir_node **preds = obstack_finish(&env->preds_obst);
{%- endif %}
{%- if node.constructorFlags %}
ir_cons_flags flags = cons_none;
{%- endif %}
ir_node *res;
{%- if node.constructorFlags %}
{%- for attr in node.attrs %}
{%- if "to_flags" in attr %}
flags |= {{attr.to_flags}};
{%- endif %}
{%- endfor %}
{%- if node.dynamic_pinned %}
flags |= pin_state == op_pin_state_floats ? cons_floats : 0;
{%- endif %}
{%- if "fragile" in node.flags %}
flags |= throws ? cons_throws_exception : 0;
{%- endif %}
{%- endif %}
res = new_r_{{node.name}}(
{%- filter arguments %}
{{node|block}} {{node|block}}
{{node.arguments|args}} {{node.arguments|args}}
{%- if node.dynamic_pinned and not hasattr(node, "pinned_init") %}
pin_state
{%- endif %}
{% endfilter %}); {% endfilter %});
{% for (initarg, initfunc) in node.initargs %}
{{initfunc}}(newnode, {{initarg}}); {%- if node.arity == "dynamic" or node.arity == "variable" %}
{% endfor -%} obstack_free(&env->preds_obst, preds);
break; {%- endif %}
} {%- for attr in node.extraattrs %}
set_{{node.name}}_{{attr.name}}(res, {{attr.name}});
{%- endfor %}
{%- if not node.constructorFlags %}
{%- if node.dynamic_pinned and hasattr(node, "pinned_init") %}
set_irn_pinned(res, pin_state);
{%- endif %}
{%- if "fragile" in node.flags and hasattr(node, "throws_init") %}
ir_set_throws_exception(res, throws);
{%- endif %}
{%- endif %}
return res;
}
{% endfor %}
{%- for node in nodes|notset('customSerializer') %}
static void write_{{node.name}}(write_env_t *env, const ir_node *node)
{
write_symbol(env, "{{node.name}}");
write_node_nr(env, node);
{%- if not node.knownBlock %}
write_node_ref(env, get_nodes_block(node));
{%- endif %}
{%- for input in node.ins %}
write_node_ref(env, get_{{node.name}}_{{input[0]}}(node));
{%- endfor %}
{%- if not hasattr(node, "mode") %}
write_mode_ref(env, get_irn_mode(node));
{%- endif %}
{%- for attr in node.attrs %}
{{attr.exportcmd}}
{%- endfor %}
{%- if node.dynamic_pinned %}
write_pin_state(env, get_irn_pinned(node));
{%- endif %}
{%- if "fragile" in node.flags %}
write_throws(env, ir_throws_exception(node));
{%- endif %}
{%- if node.arity == "dynamic" or node.arity == "variable" %}
write_pred_refs(env, node, {% if node.ins %}n_{{node.name}}_max+1{% else %}0{%endif%});
{%- endif %}
}
{% endfor %}
static void register_generated_node_readers(void)
{
{%- for node in nodes|notset('customSerializer') %}
register_node_reader(new_id_from_str("{{node.name}}"), read_{{node.name}});
{%- endfor %}
}
static void register_generated_node_writers(void)
{
{%- for node in nodes|notset('customSerializer') %}
register_node_writer(op_{{node.name}}, write_{{node.name}});
{%- endfor %}
}
''') ''')
def main(argv): def main(argv):
"""the main function"""
if len(argv) < 3: if len(argv) < 3:
print "usage: %s specname(ignored) destdirectory" % argv[0] print "usage: %s specname(ignored) destdirectory" % argv[0]
sys.exit(1) sys.exit(1)
...@@ -194,32 +282,11 @@ def main(argv): ...@@ -194,32 +282,11 @@ def main(argv):
for node in ir_spec.nodes: for node in ir_spec.nodes:
if isAbstract(node): if isAbstract(node):
continue continue
real_nodes.append(node)
file = open(gendir + "/gen_irio_export.inl", "w");
file.write("/* Warning: automatically generated code */")
for node in real_nodes:
if node.customSerializer:
continue
preprocess_node(node) preprocess_node(node)
file.write(export_attrs_template.render(vars())) real_nodes.append(node)
file.write("\n")
file.close()
file = open(gendir + "/gen_irio_import.inl", "w");
file.write("/* Warning: automatically generated code */")
for node in real_nodes:
if node.customSerializer:
continue
file.write(import_attrs_template.render(vars()))
file.write("\n")
file.close()
file = open(gendir + "/gen_irio_lex.inl", "w"); file = open(gendir + "/gen_irio.inl", "w");
file.write("/* Warning: automatically generated code */") file.write(io_template.render(nodes = real_nodes, hasattr=hasattr))
for node in real_nodes:
file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
file.close() file.close()
main(sys.argv) main(sys.argv)
...@@ -164,7 +164,7 @@ class Deleted(Op): ...@@ -164,7 +164,7 @@ class Deleted(Op):
flags = [ ] flags = [ ]
pinned = "yes" pinned = "yes"
noconstructor = True noconstructor = True
customSerializer = True customSerializer = True # this has no serializer
class Block(Op): class Block(Op):
"""A basic block""" """A basic block"""
...@@ -498,7 +498,6 @@ class End(Op): ...@@ -498,7 +498,6 @@ class End(Op):
knownBlock = True knownBlock = True
block = "get_irg_end_block(irg)" block = "get_irg_end_block(irg)"
singleton = True singleton = True
customSerializer = True
class Eor(Binop): class Eor(Binop):
"""returns the result of a bitwise exclusive or operation of its operands""" """returns the result of a bitwise exclusive or operation of its operands"""
...@@ -603,12 +602,14 @@ class Load(Op): ...@@ -603,12 +602,14 @@ class Load(Op):
name = "volatility", name = "volatility",
comment = "volatile loads are a visible side-effect and may not be optimized", comment = "volatile loads are a visible side-effect and may not be optimized",
init = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile", init = "flags & cons_volatile ? volatility_is_volatile : volatility_non_volatile",
to_flags = "%s == volatility_is_volatile ? cons_volatile : 0"
), ),
dict( dict(
type = "ir_align", type = "ir_align",
name = "unaligned", name = "unaligned",
comment = "pointers to unaligned loads don't need to respect the load-mode/type alignments", comment = "pointers to unaligned loads don't need to respect the load-mode/type alignments",
init = "flags & cons_unaligned ? align_non_aligned : align_is_aligned", init = "flags & cons_unaligned ? align_non_aligned : align_is_aligned",
to_flags = "%s == align_non_aligned ? cons_unaligned : 0"
), ),
] ]
attr_struct = "load_attr" attr_struct = "load_attr"
...@@ -715,6 +716,7 @@ class Phi(Op): ...@@ -715,6 +716,7 @@ class Phi(Op):
As we can't distinguish these easily we keep all of them alive. */ As we can't distinguish these easily we keep all of them alive. */
if (is_Phi(res) && mode == mode_M) if (is_Phi(res) && mode == mode_M)
add_End_keepalive(get_irg_end(irg), res);''' add_End_keepalive(get_irg_end(irg), res);'''
customSerializer = True
class Pin(Op): class Pin(Op):
"""Pin the value of the node node in the current block. No users of the Pin