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.arguments = arguments node.constructorFlags = True
node.initargs = initargs arguments.append("flags")
export_attrs_template = env.from_string(''' node.arguments = arguments
case iro_{{node.name}}: node.extraattrs = extraattrs
{{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}} node.dynamic_pinned = is_dynamic_pinned(node)
{% for attr in node.attrs %}{{attr.exportcmd}}
{% endfor %} io_template = env.from_string('''/* Warning: automatically generated code */
{% for attr in node.constructor_args %}{{attr.exportcmd}} {%- for node in nodes|notset('customSerializer') %}
{% endfor %}break;''') static ir_node *read_{{node.name}}(read_env_t *env)
{
import_attrs_template = env.from_string(''' {%- if not node.knownBlock %}
case iro_{{node.name}}: { ir_node *block = read_node_ref(env);
{{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}} {%- endif %}
{% for attr in node.attrs %} {%- for input in node.ins %}
{{attr.importcmd}} ir_node *in_{{input[0]}} = read_node_ref(env);
{% endfor -%} {%- endfor %}
{% for attr in node.constructor_args %} {%- if not hasattr(node, "mode") %}
{{attr.importcmd}} ir_mode *mode = read_mode_ref(env);
{% endfor -%} {%- endif %}
newnode = new_r_{{node.name}}( {%- for attr in node.attrs %}
{%- filter arguments %} {{attr.type}} {{attr.name}} = {{attr.importcmd}};
{%- endfor %}
{%- if node.dynamic_pinned %}
op_pin_state pin_state = read_pin_state(env);
{%- endif %}
{%- if "fragile" in node.flags %}
bool throws = read_throws(env);
{%- endif %}
{%- if node.arity == "dynamic" or node.arity == "variable" %}
int n_preds = read_preds(env);
ir_node **preds = obstack_finish(&env->preds_obst);
{%- endif %}
{%- if node.constructorFlags %}
ir_cons_flags flags = cons_none;
{%- endif %}
ir_node *res;
{%- if node.constructorFlags %}
{%- for attr in node.attrs %}
{%- if "to_flags" in attr %}
flags |= {{attr.to_flags}};
{%- endif %}
{%- endfor %}
{%- if node.dynamic_pinned %}
flags |= pin_state == op_pin_state_floats ? cons_floats : 0;
{%- endif %}
{%- if "fragile" in node.flags %}
flags |= throws ? cons_throws_exception : 0;
{%- endif %}
{%- endif %}
res = new_r_{{node.name}}(
{%- filter arguments %}
{{node|block}} {{node|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 """Pin the value of the node node in the current block. No users of the Pin
...