gen_docu: fix missing attributes, show generation time at the end
[libfirm] / scripts / gen_ir_io.py
index c7748cd..2fab4b0 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 import sys
+import re
 from jinja2 import Environment, Template
 from jinja2.filters import do_dictsort
 from spec_util import is_dynamic_pinned, verify_node, isAbstract
@@ -14,10 +15,7 @@ def warning(msg):
        sys.stderr.write("Warning: " + msg + "\n");
 
 def format_args(arglist):
-       s = ", ".join(arglist)
-       if len(s) == 0:
-         return ""
-       return ", " + s
+       return "\n".join(arglist)
 
 def format_ifnset(string, node, key):
        if hasattr(node, key):
@@ -26,44 +24,54 @@ def format_ifnset(string, node, key):
 
 def format_block(node):
        if hasattr(node, "knownBlock"):
-               return "current_ir_graph"
+               if hasattr(node, "knownGraph"):
+                       return ""
+               return "irg"
        else:
-               return "get_node(env, preds[0])"
+               return "preds[0]"
+
+def format_arguments(string):
+       args = re.split('\s*\n\s*', string)
+       if args[0] == '':
+               args = args[1:]
+       if len(args) > 0 and args[-1] == '':
+               args = args[:-1]
+       return ", ".join(args)
 
 env = Environment()
-env.filters['args']   = format_args
-env.filters['ifnset'] = format_ifnset
-env.filters['block']  = format_block
+env.filters['args']      = format_args
+env.filters['ifnset']    = format_ifnset
+env.filters['block']     = format_block
+env.filters['arguments'] = format_arguments
 
 def get_io_type(type, attrname, node):
-       if type == "tarval*":
-               importcmd = "tarval *%s = read_tv(env);" % attrname
+       if type == "ir_tarval*":
+               importcmd = "ir_tarval *%s = read_tv(env);" % attrname
                exportcmd = "write_tarval(env, %(val)s);";
        elif type == "ir_mode*":
                importcmd = "ir_mode *%s = read_mode(env);" % attrname
                exportcmd = "write_mode(env, %(val)s);"
        elif type == "ir_entity*":
                importcmd = "ir_entity *%s = read_entity(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%ld ", get_entity_nr(%(val)s));"""
+               exportcmd = "write_entity_ref(env, %(val)s);"
        elif type == "ir_type*":
                importcmd = "ir_type *%s = read_type(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%ld ", get_type_nr(%(val)s));"""
+               exportcmd = "write_type_ref(env, %(val)s);"
        elif type == "long" and node.name == "Proj":
                importcmd = "long %s = read_long(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
-       elif type == "pn_Cmp" or type == "ir_where_alloc":
+               exportcmd = "write_long(env, %(val)s);"
+       elif type == "ir_relation" or type == "ir_where_alloc":
                importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
-               exportcmd = """fprintf(env->file, "%%ld ", (long) %(val)s);"""
-       elif type == "ir_cons_flags" and node.name == "Store":
-               importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
-               exportcmd = """write_pin_state(env, irn);
-                       write_volatility(env, irn);
-                       write_align(env, irn);"""
-       elif type == "ir_cons_flags" and node.name == "Load":
-               importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
-               exportcmd = """write_pin_state(env, irn);
-                       write_volatility(env, irn);
-                       write_align(env, irn);"""
+               exportcmd = "write_long(env, (long) %(val)s);"
+       elif type == "ir_align":
+               importcmd = "ir_align %s = read_align(env);" % attrname
+               exportcmd = "write_align(env, %(val)s);"
+       elif type == "ir_volatility":
+               importcmd = "ir_volatility %s = read_volatility(env);" % attrname
+               exportcmd = "write_volatility(env, %(val)s);"
+       elif type == "ir_cons_flags":
+               importcmd = "ir_cons_flags %s = cons_none;" % attrname
+               exportcmd = "" # can't really export cons_flags
        elif type == "op_pin_state":
                importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
                exportcmd = "write_pin_state(env, irn);"
@@ -77,16 +85,16 @@ def get_io_type(type, attrname, node):
                importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
                exportcmd = "write_cond_jmp_predicate(env, irn);"
        elif type == "int":
-               importcmd = "int %s = (int) read_long(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
+               importcmd = "int %s = read_int(env);" % attrname
+               exportcmd = "write_int(env, %(val)s);"
        elif type == "unsigned":
-               importcmd = "unsigned %s = (unsigned) read_long(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%u ", %(val)s);"""
+               importcmd = "unsigned %s = read_unsigned(env);" % attrname
+               exportcmd = "write_unsigned(env, %(val)s);"
        elif type == "long":
                importcmd = "long %s = read_long(env);" % attrname
-               exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
+               exportcmd = "write_long(env, %(val)s);"
        else:
-               error("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
                        %s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
                exportcmd = "// BAD: %s" % type
@@ -114,49 +122,21 @@ def preprocess_node(node):
        # construct node arguments
        arguments = [ ]
        initargs = [ ]
-       specialconstrs = [ ]
-       i = 0
+       i = 1
        for input in node.ins:
-               arguments.append("prednodes[%i]" % i)
+               arguments.append("preds[%i]" % i)
                i += 1
 
        if node.arity == "variable" or node.arity == "dynamic":
-               arguments.append("numpreds - %i" % (i + 1))
-               arguments.append("prednodes + %i" % i)
+               arguments.append("numpreds - %i" % i)
+               arguments.append("preds + %i" % i)
 
        if not hasattr(node, "mode"):
                arguments.append("mode")
 
-       attrs_with_special = 0
        for attr in node.attrs:
                prepare_attr(node, attr)
-               if "special" in attr:
-                       if not "init" in attr:
-                               warning("Node type %s has an attribute with a \"special\" entry but without \"init\"" % node.name)
-                               sys.exit(1)
-
-                       if attrs_with_special != 0:
-                               warning("Node type %s has more than one attribute with a \"special\" entry" % node.name)
-                               sys.exit(1)
-
-                       attrs_with_special += 1
-
-                       if "prefix" in attr["special"]:
-                               specialname = attr["special"]["prefix"] + node.name
-                       elif "suffix" in attr["special"]:
-                               specialname = node.name + attr["special"]["suffix"]
-                       else:
-                               error("Unknown special constructor type for node type %s" % node.name)
-                               sys.exit(1)
-
-                       specialconstrs.append(
-                               dict(
-                                       constrname = specialname,
-                                       attrname = attr["name"],
-                                       value = attr["special"]["init"]
-                               )
-                       )
-               elif "init" in attr:
+               if "init" in attr:
                        if attr["type"] == "op_pin_state":
                                initfunc = "set_irn_pinned"
                        else:
@@ -171,7 +151,6 @@ def preprocess_node(node):
 
        node.arguments = arguments
        node.initargs = initargs
-       node.special_constructors = specialconstrs
 
 export_attrs_template = env.from_string('''
        case iro_{{node.name}}:
@@ -182,19 +161,22 @@ export_attrs_template = env.from_string('''
                {% endfor %}break;''')
 
 import_attrs_template = env.from_string('''
-       case iro_{{node.name}}:
-       {
+       case iro_{{node.name}}: {
                {{"ir_mode *mode = read_mode(env);"|ifnset(node,"mode")}}
-               {% for attr in node.attrs %}{{attr.importcmd}}
-               {% endfor %}
-               {% for attr in node.constructor_args %}{{attr.importcmd}}
-               {% endfor %}
-               {% for special in node.special_constructors %}if({{special.attrname}} == {{special.value}})
-                       newnode = new_r_{{special.constrname}}({{node|block}}{{node.arguments|args}});
-               else{% endfor %}
-               newnode = new_r_{{node.name}}({{node|block}}{{node.arguments|args}});
-               {% for (initarg, initfunc) in node.initargs %}{{initfunc}}(newnode, {{initarg}});
-               {% endfor %}
+               {% for attr in node.attrs %}
+               {{attr.importcmd}}
+               {% endfor -%}
+               {% for attr in node.constructor_args %}
+               {{attr.importcmd}}
+               {% endfor -%}
+               newnode = new_r_{{node.name}}(
+{%- filter arguments %}
+{{node|block}}
+{{node.arguments|args}}
+{% endfilter %});
+               {% for (initarg, initfunc) in node.initargs %}
+               {{initfunc}}(newnode, {{initarg}});
+               {% endfor -%}
                break;
        }
 ''')
@@ -207,10 +189,6 @@ def main(argv):
                sys.exit(1)
 
        gendir = argv[2]
-       # these nodes don't work correctly yet for some reasons...
-       niynodes = [ "EndExcept", "EndReg", "ASM" ]
-       # these have custom im-/export code
-       customcode = [ "Start", "End", "Anchor", "SymConst", "Block" ]
 
        real_nodes = []
        for node in ir_spec.nodes:
@@ -219,8 +197,9 @@ def main(argv):
                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.__name__ in niynodes:
+               if node.customSerializer:
                        continue
 
                preprocess_node(node)
@@ -229,17 +208,17 @@ def main(argv):
        file.close()
 
        file = open(gendir + "/gen_irio_import.inl", "w");
+       file.write("/* Warning: automatically generated code */")
        for node in real_nodes:
-               if node.name in customcode or node.name in niynodes:
+               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.write("/* Warning: automatically generated code */")
        for node in real_nodes:
-               if node.name in niynodes:
-                       continue
                file.write("\tINSERT(tt_iro, \"%s\", iro_%s);\n" % (node.name, node.name));
        file.close()