let Bad and NoMem nodes get automatically generated
[libfirm] / scripts / gen_ir.py
index 8f30822..c6badca 100755 (executable)
@@ -57,18 +57,19 @@ def format_insdecl(node):
 
        if arity == "variable":
                insarity = len(node.ins)
-               res = "int r_arity = arity + " + `insarity` + ";\n\tir_node **r_in;\n\t" \
-                       + "NEW_ARR_A(ir_node *, r_in, r_arity);\n\t"
+               res  = "int r_arity = arity + " + `insarity` + ";"
+               res += "\n\tir_node **r_in;"
+               res += "\n\tNEW_ARR_A(ir_node *, r_in, r_arity);"
                i = 0
                for input in node.ins:
-                       res += "r_in[" + `i` + "] = irn_" + input + ";\n\t"
+                       res += "\n\tr_in[" + `i` + "] = irn_" + input + ";"
                        i += 1
-               res += "memcpy(&r_in[" + `insarity` + "], in, sizeof(ir_node *) * arity);\n\t"
+               res += "\n\tmemcpy(&r_in[" + `insarity` + "], in, sizeof(ir_node *) * arity);\n\t"
        else:
-               res = "ir_node *in[" + `arity` + "];\n\t"
+               res = "ir_node *in[" + `arity` + "];"
                i = 0
                for input in node.ins:
-                       res += "in[" + `i` + "] = irn_" + input + ";\n\t"
+                       res += "\n\tin[" + `i` + "] = irn_" + input + ";"
                        i += 1
        return res
 
@@ -133,6 +134,12 @@ def format_opindex(node):
                return node.op_index
        return "-1"
 
+keywords = frozenset([ "true", "false" ])
+def format_escape_keywords(word):
+       if word in keywords:
+               return word + "_"
+       return word
+
 def filter_isnot(list, flag):
        return filter(lambda x: not hasattr(x, flag), list)
 
@@ -153,24 +160,25 @@ def format_parameters(string):
        return format_arguments(string, voidwhenempty = True)
 
 env = Environment()
-env.filters['parameterlist']  = format_parameterlist
-env.filters['nodearguments']  = format_nodearguments
-env.filters['nodeparameters'] = format_nodeparameters
-env.filters['blockparameter'] = format_blockparameter
-env.filters['blockargument']  = format_blockargument
-env.filters['irgassign']      = format_irgassign
-env.filters['curblock']       = format_curblock
-env.filters['insdecl']        = format_insdecl
-env.filters['arity_and_ins']  = format_arity_and_ins
-env.filters['arity']          = format_arity
-env.filters['pinned']         = format_pinned
-env.filters['flags']          = format_flags
-env.filters['attr_size']      = format_attr_size
-env.filters['opindex']        = format_opindex
-env.filters['isnot']          = filter_isnot
-env.filters['hasnot']         = filter_hasnot
-env.filters['arguments']      = format_arguments
-env.filters['parameters']     = format_parameters
+env.filters['parameterlist']   = format_parameterlist
+env.filters['nodearguments']   = format_nodearguments
+env.filters['nodeparameters']  = format_nodeparameters
+env.filters['blockparameter']  = format_blockparameter
+env.filters['blockargument']   = format_blockargument
+env.filters['irgassign']       = format_irgassign
+env.filters['curblock']        = format_curblock
+env.filters['insdecl']         = format_insdecl
+env.filters['arity_and_ins']   = format_arity_and_ins
+env.filters['arity']           = format_arity
+env.filters['pinned']          = format_pinned
+env.filters['flags']           = format_flags
+env.filters['attr_size']       = format_attr_size
+env.filters['opindex']         = format_opindex
+env.filters['isnot']           = filter_isnot
+env.filters['hasnot']          = filter_hasnot
+env.filters['arguments']       = format_arguments
+env.filters['parameters']      = format_parameters
+env.filters['escape_keywords'] = format_escape_keywords
 
 def prepare_attr(attr):
        if "init" in attr:
@@ -277,10 +285,12 @@ ir_node *new_rd_{{node.constrname}}(
        {% endfilter %})
 {
        ir_node *res;
-       ir_graph *rem = current_ir_graph;
+       {%- if node.arity == "dynamic" %}
+       int      i;
+       {%- endif %}
        {{node|irgassign}}
        {{node|insdecl}}
-       current_ir_graph = irg;
+
        res = new_ir_node(
                {%- filter arguments %}
                        dbgi
@@ -290,21 +300,23 @@ ir_node *new_rd_{{node.constrname}}(
                        {{node.mode}}
                        {{node|arity_and_ins}}
                {% endfilter %});
-       {% for attr in node.attrs -%}
-               res->attr.{{node.attrs_name}}{{attr["initname"]}} =
+       {%- if node.arity == "dynamic" %}
+       for (i = 0; i < arity; ++i) {
+               add_irn_n(res, in[i]);
+       }
+       {%- endif %}
+       {%- for attr in node.attrs %}
+       res->attr.{{node.attrs_name}}{{attr["initname"]}} =
                {%- if "init" in attr %} {{ attr["init"] -}};
                {%- else              %} {{ attr["name"] -}};
-               {% endif %}
-       {% endfor %}
-       {%- for attr in node.initattrs -%}
-               res->attr.{{node.attrs_name}}{{attr["initname"]}} = {{ attr["init"] -}};
+               {%- endif %}
+       {%- endfor %}
+       {%- for attr in node.initattrs %}
+       res->attr.{{node.attrs_name}}{{attr["initname"]}} = {{ attr["init"] -}};
        {%- endfor %}
        {{- node.init }}
-       {% if node.optimize != False -%}
-               res = optimize_node(res);
-       {% endif -%}
-       IRN_VRFY_IRG(res, irg);
-       current_ir_graph = rem;
+       res = optimize_node(res);
+       irn_verify_irg(res, irg);
        return res;
 }
 
@@ -329,14 +341,13 @@ ir_node *new_d_{{node.constrname}}(
                {% endfilter %})
 {
        ir_node *res;
-       {{ node.d_pre }}
+       assert(get_irg_phase_state(current_ir_graph) == phase_building);
        res = new_rd_{{node.constrname}}(
                {%- filter parameters %}
                        dbgi
                        {{node|curblock}}
                        {{node|nodearguments}}
                {% endfilter %});
-       {{ node.d_post }}
        return res;
 }
 
@@ -403,10 +414,10 @@ ir_node *(get_{{node.name}}_{{in}})(const ir_node *node)
        return get_irn_n(node, {{node.ins.index(in)}});
 }
 
-void (set_{{node.name}}_{{in}})(ir_node *node, ir_node *{{in}})
+void (set_{{node.name}}_{{in}})(ir_node *node, ir_node *{{in|escape_keywords}})
 {
        assert(is_{{node.name}}(node));
-       set_irn_n(node, {{node.ins.index(in)}}, {{in}});
+       set_irn_n(node, {{node.ins.index(in)}}, {{in|escape_keywords}});
 }
 {% endfor %}
 {% endfor %}
@@ -446,8 +457,17 @@ void finish_op(void)
 
 ''')
 
-projnumbers_h_template = env.from_string('''
+nodeops_h_template = env.from_string('''
 /* Warning: automatically generated code */
+#ifndef FIRM_IR_NODEOPS_H
+#define FIRM_IR_NODEOPS_H
+
+#include "firm_types.h"
+
+/**
+ * @addtogroup ir_node
+ * @{
+ */
 
 {% for node in nodes -%}
 {% if node.outs %}
@@ -464,6 +484,71 @@ typedef enum {
 {% endif %}
 {%- endfor %}
 
+{% for node in nodes %}
+/** Return true of the node is a {{node.name}} node. */
+FIRM_API int is_{{node.name}}(const ir_node *node);
+{%- endfor %}
+
+{% for node in nodes %}
+{% for in in node.ins -%}
+FIRM_API ir_node *get_{{node.name}}_{{in}}(const ir_node *node);
+void set_{{node.name}}_{{in}}(ir_node *node, ir_node *{{in|escape_keywords}});
+{% endfor -%}
+{% for attr in node.attrs|hasnot("noprop") -%}
+FIRM_API {{attr.type}} get_{{node.name}}_{{attr.name}}(const ir_node *node);
+FIRM_API void set_{{node.name}}_{{attr.name}}(ir_node *node, {{attr.type}} {{attr.name}});
+{% endfor -%}
+{% endfor -%}
+
+/** @} */
+
+#endif
+''')
+
+opcodes_h_template = env.from_string('''
+/* Warning: automatically generated code */
+#ifndef FIRM_IR_OPCODES_H
+#define FIRM_IR_OPCODES_H
+
+/** The opcodes of the libFirm predefined operations. */
+typedef enum ir_opcode {
+{%- for node in nodes %}
+       iro_{{node.name}},
+{%- endfor %}
+       iro_First = iro_{{nodes[0].name}},
+       iro_Last = iro_{{nodes[-1].name}},
+
+       beo_First,
+       /* backend specific nodes */
+       beo_Spill = beo_First,
+       beo_Reload,
+       beo_Perm,
+       beo_MemPerm,
+       beo_Copy,
+       beo_Keep,
+       beo_CopyKeep,
+       beo_Call,
+       beo_Return,
+       beo_AddSP,
+       beo_SubSP,
+       beo_IncSP,
+       beo_Start,
+       beo_FrameAddr,
+       beo_Barrier,
+       /* last backend node number */
+       beo_Last = beo_Barrier,
+       iro_MaxOpcode
+} ir_opcode;
+
+{% for node in nodes %}
+FIRM_API ir_op *op_{{node.name}};
+{%- endfor %}
+
+{% for node in nodes %}
+FIRM_API ir_op *get_op_{{node.name}}(void);
+{%- endfor %}
+
+#endif
 ''')
 
 #############################
@@ -490,7 +575,7 @@ def main(argv):
        gendir2 = argv[2] + "/../../include/libfirm"
 
        # List of TODOs
-       niymap = [ "ASM", "Const", "Phi", "SymConst", "Sync"]
+       niymap = [ "ASM", "Const", "Phi", "SymConst" ]
 
        real_nodes = prepare_nodes()
        file = open(gendir + "/gen_ir_cons.c.inl", "w")
@@ -498,7 +583,7 @@ def main(argv):
                if node.name in niymap:
                        continue
 
-               if not isAbstract(node) and not hasattr(node, "singleton"):
+               if not isAbstract(node) and not hasattr(node, "noconstructor"):
                        file.write(constructor_template.render(vars()))
 
                        if hasattr(node, "special_constructors"):
@@ -521,8 +606,12 @@ def main(argv):
        file.write(irop_template.render(nodes = real_nodes))
        file.close()
 
-       file = open(gendir2 + "/projnumbers.h", "w")
-       file.write(projnumbers_h_template.render(nodes = real_nodes))
+       file = open(gendir2 + "/opcodes.h", "w")
+       file.write(opcodes_h_template.render(nodes = real_nodes))
+       file.close()
+
+       file = open(gendir2 + "/nodeops.h", "w")
+       file.write(nodeops_h_template.render(nodes = real_nodes))
        file.close()
 
 main(sys.argv)