Commit b4dbd5b7 authored by Matthias Braun's avatar Matthias Braun
Browse files

refactor generator scripts

Templates are put in separate files now, making the main script more
generic in nature
parent feab0134
......@@ -56,11 +56,6 @@ all: firm
# disable make builtin suffix rules
.SUFFIXES:
# This rule is necessary so that make does not abort if headers get deleted
# (the deleted header might still be referenced in a .d file)
%.h:
@:
# libFirm
libfirm_SOURCES = $(wildcard ir/*/*.c)
libfirm_DIRS = $(sort $(dir $(libfirm_SOURCES)))
......@@ -119,24 +114,31 @@ IR_SPEC_GENERATED_FILES := \
include/libfirm/nodeops.h \
include/libfirm/opcodes.h \
ir/ir/gen_ir_cons.c.inl \
ir/ir/gen_irop.c.inl \
ir/ir/gen_irdump.c.inl \
ir/ir/gen_irnode.c.inl \
ir/ir/gen_irnode.h
ir/ir/gen_irnode.h \
ir/ir/gen_irop.c.inl
IR_SPEC_GENERATOR := scripts/gen_ir.py
IR_SPEC_GENERATOR_DEPS := $(IR_SPEC_GENERATOR) scripts/spec_util.py scripts/filters.py
IR_SPEC := scripts/ir_spec.py
$(IR_SPEC_GENERATED_FILES): $(IR_SPEC_GENERATOR) $(IR_SPEC) scripts/spec_util.py
ir/ir/% : scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(IR_SPEC)
@echo GEN $@
$(Q)$(IR_SPEC_GENERATOR) $(IR_SPEC) $< > $@
include/libfirm/% : scripts/templates/% $(IR_SPEC_GENERATOR_DEPS) $(IR_SPEC)
@echo GEN $@
$(Q)$(IR_SPEC_GENERATOR) $(IR_SPEC) ir/ir
$(Q)$(IR_SPEC_GENERATOR) $(IR_SPEC) $< > $@
IR_IO_GENERATED_FILES := ir/ir/gen_irio.c.inl
IR_IO_GENERATOR := scripts/gen_ir_io.py
IR_IO_GENERATED_FILES := ir/ir/gen_irio.inl
IR_IO_GENERATOR_DEPS := $(IR_IO_GENERATOR) scripts/spec_util.py scripts/filters.py
$(IR_IO_GENERATED_FILES): $(IR_IO_GENERATOR) $(IR_SPEC) scripts/spec_util.py
@echo GEN $@
$(Q)$(IR_IO_GENERATOR) $(IR_SPEC) ir/ir
ir/ir/irio.c : ir/ir/gen_irio.c.inl
ir/ir/irio.c: $(IR_IO_GENERATED_FILES)
ir/ir/% : scripts/templates_io/% $(IR_IO_GENERATOR_DEPS) $(IR_SPEC)
@echo GEN $@
$(Q)$(IR_IO_GENERATOR) $(IR_SPEC) $< > $@
libfirm_OBJECTS = $(libfirm_SOURCES:%.c=$(builddir)/%.o)
libfirm_DEPS = $(libfirm_OBJECTS:%.o=%.d)
......@@ -178,3 +180,8 @@ doc: $(docdir)/libfirm.tag $(docdir)/html/nodes.html
clean:
@echo CLEAN
$(Q)rm -fr $(builddir) $(shell find ir/ -name "gen_*.[ch]")
# This rule is necessary so that make does not abort if headers get deleted
# (the deleted header might still be referenced in a .d file)
%.h:
@:
......@@ -2455,4 +2455,4 @@ int ir_import_file(FILE *input, const char *inputname)
return env->read_errors;
}
#include "gen_irio.inl"
#include "gen_irio.c.inl"
......@@ -3,7 +3,7 @@
# This file is part of libFirm.
# Copyright (C) 2012 Karlsruhe Institute of Technology.
import sys
from jinja2 import Environment, Template
from jinja2 import Environment, Template, FileSystemLoader
from spec_util import is_dynamic_pinned, isAbstract, setdefault, load_spec
from filters import format_arguments, filter_isnot, filter_hasnot, filter_notset
......@@ -155,7 +155,7 @@ def format_escape_keywords(word):
def format_parameters(string):
return format_arguments(string, voidwhenempty = True)
env = Environment()
env = Environment(loader=FileSystemLoader("."))
env.filters['a_an'] = format_a_an
env.filters['parameterlist'] = format_parameterlist
env.filters['nodearguments'] = format_nodearguments
......@@ -259,489 +259,6 @@ def preprocess_node(node):
node.arguments = arguments
node.initattrs = initattrs
#############################
gen_ircons_c_inl_template = env.from_string(
'''/* Warning: automatically generated code */
{%- for node in nodes %}
{%- if not node.noconstructor %}
ir_node *new_rd_{{node.name}}(
{%- filter parameters %}
dbg_info *dbgi
{{node|blockparameter}}
{{node|nodeparameters}}
{% endfilter %})
{
{{node|irgassign}}
{{node|insdecl}}
ir_node *res = new_ir_node(
{%- filter arguments %}
dbgi
irg
{{node.block}}
op_{{node.name}}
{{node.mode}}
{{node|arity_and_ins}}
{% endfilter %});
{%- if node.arity == "dynamic" %}
for (int i = 0; i < arity; ++i) {
add_irn_n(res, in[i]);
}
{%- endif %}
{%- for attr in node.attrs %}
res->attr.{{node.attrs_name}}{{attr["fqname"]}} =
{%- if "init" in attr %} {{ attr["init"] -}};
{%- else %} {{ attr["name"] -}};
{%- endif %}
{%- endfor %}
{%- for attr in node.initattrs %}
res->attr.{{node.attrs_name}}{{attr["fqname"]}} = {{ attr["init"] -}};
{%- endfor %}
{{- node.init }}
irn_verify_irg(res, irg);
res = optimize_node(res);
{{- node.init_after_opt }}
return res;
}
ir_node *new_r_{{node.name}}(
{%- filter parameters %}
{{node|blockparameter}}
{{node|nodeparameters}}
{% endfilter %})
{
return new_rd_{{node.name}}(
{%- filter arguments %}
NULL
{{node|blockargument}}
{{node|nodearguments}}
{% endfilter %});
}
ir_node *new_d_{{node.name}}(
{%- filter parameters %}
dbg_info *dbgi
{{node|nodeparameters}}
{% endfilter %})
{
assert(irg_is_constrained(current_ir_graph, IR_GRAPH_CONSTRAINT_CONSTRUCTION));
ir_node *res = new_rd_{{node.name}}(
{%- filter parameters %}
dbgi
{{node|curblock}}
{{node|nodearguments}}
{% endfilter %});
return res;
}
ir_node *new_{{node.name}}(
{%- filter parameters %}
{{node|nodeparameters}}
{% endfilter %})
{
return new_d_{{node.name}}(
{%- filter arguments %}
NULL
{{node|nodearguments}}
{% endfilter %});
}
{% endif %}
{%- endfor %}
''')
irnode_h_template = env.from_string(
'''/* Warning: automatically generated code */
{% for node in nodes %}
#define is_{{node.name}}(node) is_{{node.name}}_(node)
{%- for attr in node.attrs|hasnot("noprop") %}
#define get_{{node.name}}_{{attr.name}}(node) get_{{node.name}}_{{attr.name}}_(node)
#define set_{{node.name}}_{{attr.name}}(node, {{attr.name}}) set_{{node.name}}_{{attr.name}}_(node, {{attr.name}})
{%- endfor -%}
{%- for input in node.ins %}
#define get_{{node.name}}_{{input[0]}}(node) get_{{node.name}}_{{input[0]}}_(node)
#define set_{{node.name}}_{{input[0]}}(node, {{input[0]|escape_keywords}}) set_{{node.name}}_{{input[0]}}_(node, {{input[0]|escape_keywords}})
{%- endfor -%}
{%- if node.input_name %}
#define get_{{node.name}}_n_{{node.input_name}}s(node) get_{{node.name}}_n_{{node.input_name}}s_(node)
#define get_{{node.name}}_{{node.input_name}}(node, pos) get_{{node.name}}_{{node.input_name}}_(node, pos)
#define set_{{node.name}}_{{node.input_name}}(node, pos, {{node.input_name}}) set_{{node.name}}_{{node.input_name}}_(node, pos, {{node.input_name}})
#define get_{{node.name}}_{{node.input_name}}_arr(node) get_{{node.name}}_{{node.input_name}}_arr_(node)
{%- endif %}
{% endfor %}
{%- for node in nodes %}
static inline int is_{{node.name}}_(const ir_node *node)
{
return get_irn_op(node) == op_{{node.name}};
}
{% for attr in node.attrs|hasnot("noprop") %}
static inline {{attr.type}} get_{{node.name}}_{{attr.name}}_(const ir_node *node)
{
assert(is_{{node.name}}(node));
return node->attr.{{node.attrs_name}}.{{attr.name}};
}
static inline void set_{{node.name}}_{{attr.name}}_(ir_node *node, {{attr.type}} {{attr.name}})
{
assert(is_{{node.name}}(node));
node->attr.{{node.attrs_name}}.{{attr.name}} = {{attr.name}};
}
{% endfor -%}
{%- for input in node.ins %}
static inline ir_node *get_{{node.name}}_{{input[0]}}_(const ir_node *node)
{
assert(is_{{node.name}}(node));
return get_irn_n(node, n_{{node.name}}_{{input[0]}});
}
static inline void set_{{node.name}}_{{input[0]}}_(ir_node *node, ir_node *{{input[0]|escape_keywords}})
{
assert(is_{{node.name}}(node));
set_irn_n(node, n_{{node.name}}_{{input[0]}}, {{input[0]|escape_keywords}});
}
{% endfor %}
{%- if node.input_name %}
static inline int get_{{node.name}}_n_{{node.input_name}}s_(ir_node const *node)
{
assert(is_{{node.name}}(node));
return get_irn_arity(node){% if node.ins %} - (n_{{node.name}}_max + 1){% endif %};
}
static inline ir_node *get_{{node.name}}_{{node.input_name}}_(ir_node const *node, int pos)
{
assert(0 <= pos && pos < get_{{node.name}}_n_{{node.input_name}}s(node));
return get_irn_n(node, pos{% if node.ins %} + (n_{{node.name}}_max + 1){% endif %});
}
static inline void set_{{node.name}}_{{node.input_name}}_(ir_node *node, int pos, ir_node *{{node.input_name}})
{
assert(0 <= pos && pos < get_{{node.name}}_n_{{node.input_name}}s(node));
set_irn_n(node, pos{% if node.ins %} + (n_{{node.name}}_max + 1){% endif %}, {{node.input_name}});
}
static inline ir_node **get_{{node.name}}_{{node.input_name}}_arr_(ir_node *node)
{
assert(is_{{node.name}}(node));
return get_irn_in(node) + 1{% if node.ins %}+ (n_{{node.name}}_max + 1){% endif %};
}
{% endif -%}
{% endfor -%}
''')
irnode_template = env.from_string(
'''/* Warning: automatically generated code */
{% for node in nodes %}
int (is_{{node.name}})(const ir_node *node)
{
return is_{{node.name}}_(node);
}
{% for attr in node.attrs|hasnot("noprop") %}
{{attr.type}} (get_{{node.name}}_{{attr.name}})(const ir_node *node)
{
return get_{{node.name}}_{{attr.name}}_(node);
}
void (set_{{node.name}}_{{attr.name}})(ir_node *node, {{attr.type}} {{attr.name}})
{
set_{{node.name}}_{{attr.name}}_(node, {{attr.name}});
}
{% endfor -%}
{%- for input in node.ins %}
ir_node *(get_{{node.name}}_{{input[0]}})(const ir_node *node)
{
return get_{{node.name}}_{{input[0]}}(node);
}
void (set_{{node.name}}_{{input[0]}})(ir_node *node, ir_node *{{input[0]|escape_keywords}})
{
set_{{node.name}}_{{input[0]}}_(node, {{input[0]|escape_keywords}});
}
{% endfor %}
{%- if node.input_name %}
int (get_{{node.name}}_n_{{node.input_name}}s)(ir_node const *node)
{
return get_{{node.name}}_n_{{node.input_name}}s_(node);
}
ir_node *(get_{{node.name}}_{{node.input_name}})(ir_node const *node, int pos)
{
return get_{{node.name}}_{{node.input_name}}_(node, pos);
}
void (set_{{node.name}}_{{node.input_name}})(ir_node *node, int pos, ir_node *{{node.input_name}})
{
set_{{node.name}}_{{node.input_name}}_(node, pos, {{node.input_name}});
}
ir_node **(get_{{node.name}}_{{node.input_name}}_arr)(ir_node *node)
{
return get_{{node.name}}_{{node.input_name}}_arr_(node);
}
{% endif -%}
{% endfor %}
''')
irdump_template = env.from_string(
'''/* Warning: automatically generated code */
{% for node in nodes %}
{%- if node.outs %}
static const pns_lookup_t {{node.name}}_lut[] = {
{%- for out in node.outs %}
{ pn_{{node.name}}_{{out[0]}}, "{{out[0]}}" },
{%- endfor %}
};
{% endif -%}
{%- endfor %}
static const proj_lookup_t proj_lut[] = {
{%- for node in nodes -%}
{%- if node.outs %}
{ {{spec.name}}o_{{node.name}}, ARRAY_SIZE({{node.name}}_lut), {{node.name}}_lut },
{%- endif %}
{%- endfor %}
};
''')
irop_template = env.from_string(
'''/* Warning: automatically generated code */
{% for node in nodes %}
ir_op *op_{{node.name}}; ir_op *get_op_{{node.name}}(void) { return op_{{node.name}}; }
{%- endfor %}
static void generated_init_op(void)
{
{%- for node in nodes %}
op_{{node.name}} = new_ir_op(
{%- filter arguments %}
{{spec.name}}o_{{node.name}}
"{{node.name}}"
{{node|pinned}}
{{node|flags}}
{{node|arity}}
{{node|opindex}}
{{node|attr_size}}
{% endfilter %});
{%- if "uses_memory" in node.flags: %}
ir_op_set_memory_index(op_{{node.name}}, n_{{node.name}}_mem);
{%- endif -%}
{%- if "fragile" in node.flags: %}
ir_op_set_fragile_indices(op_{{node.name}}, pn_{{node.name}}_X_regular, pn_{{node.name}}_X_except);
{%- endif -%}
{%- endfor %}
}
static void generated_finish_op(void)
{
{%- for node in nodes %}
free_ir_op(op_{{node.name}}); op_{{node.name}} = NULL;
{%- endfor %}
}
''')
nodeops_h_template = env.from_string(
'''/* Warning: automatically generated code */
#ifndef FIRM_IR_NODEOPS_H
#define FIRM_IR_NODEOPS_H
#include "firm_types.h"
#include "begin.h"
/**
* @addtogroup ir_node
* @{
*/
{% for node in nodes -%}
/**
* @defgroup {{node.name}} {{node.name}} node
*
* {{node.doc}}
* @{
*/
{% if node.ins %}
/**
* Input numbers for {{node.name}} node
*/
typedef enum {
{%- for input in node.ins %}
n_{{node.name}}_{{input[0]}},
{%- endfor %}
n_{{node.name}}_max = n_{{node.name}}_{{node.ins[-1][0]}}
} n_{{node.name}};
{% endif -%}
{% if node.outs %}
/**
* Projection numbers for result of {{node.name}} node (use for Proj nodes)
*/
typedef enum {
{% for out in node.outs -%}
pn_{{node.name}}_{{out[0]}}
{%- if out.__len__() > 2 %} = {{out[2]}}{% endif %}, /**< {{out[1]}} */
{% endfor -%}
pn_{{node.name}}_max = pn_{{node.name}}_{{node.outs[-1][0]}}
} pn_{{node.name}};
{% endif %}
{%- if not node.noconstructor %}
/**
* Construct {{node.name|a_an}} node.
*
* @param dbgi A pointer to debug information.
{{ node|blockparameterhelp -}}
{{ node|nodeparametershelp -}}
*/
FIRM_API ir_node *new_rd_{{node.name}}(
{%- filter parameters %}
dbg_info *dbgi
{{node|blockparameter}}
{{node|nodeparameters}}
{% endfilter %});
/**
* Construct {{node.name|a_an}} node.
*
{{ node|blockparameterhelp -}}
{{ node|nodeparametershelp -}}
*/
FIRM_API ir_node *new_r_{{node.name}}(
{%- filter parameters %}
{{node|blockparameter}}
{{node|nodeparameters}}
{% endfilter %});
/**
* Construct {{node.name|a_an}} node.
*
* @param dbgi A pointer to debug information.
{{ node|nodeparametershelp -}}
*/
FIRM_API ir_node *new_d_{{node.name}}(
{%- filter parameters %}
dbg_info *dbgi
{{node|nodeparameters}}
{% endfilter %});
/**
* Construct {{node.name|a_an}} node.
*
{{ node|nodeparametershelp -}}
*/
FIRM_API ir_node *new_{{node.name}}(
{%- filter parameters %}
{{node|nodeparameters}}
{% endfilter %});
{%- endif %}
/**
* Test if node is a {{node.name}}
* @returns 1 if the node is a {{node.name}} node, 0 otherwise
*/
FIRM_API int is_{{node.name}}(const ir_node *node);
{% for input in node.ins -%}
/** Returns {{input[0]}} input of {{node.name|a_an}} node. */
FIRM_API ir_node *get_{{node.name}}_{{input[0]}}(const ir_node *node);
/** Sets {{input[0]}} input of {{node.name|a_an}} node. */
FIRM_API void set_{{node.name}}_{{input[0]}}(ir_node *node, ir_node *{{input[0]|escape_keywords}});
{% endfor -%}
{%- if node.input_name -%}
/** Get the number of {{node.name}} {{node.input_name}}s. */
FIRM_API int get_{{node.name}}_n_{{node.input_name}}s(ir_node const *node);
/** Get the {{node.name}} {{node.input_name}} with index @p pos. */
FIRM_API ir_node *get_{{node.name}}_{{node.input_name}}(ir_node const *node, int pos);
/** Set the {{node.name}} {{node.input_name}} with index @p pos. */
FIRM_API void set_{{node.name}}_{{node.input_name}}(ir_node *node, int pos, ir_node *{{node.input_name}});
/** Get an array of all {{node.name}} {{node.input_name}}s. */
ir_node **get_{{node.name}}_{{node.input_name}}_arr(ir_node *node);
{% endif -%}
{%- for attr in node.attrs|hasnot("noprop") %}
/** Returns {{attr.name}} attribute of {{node.name|a_an}} node. */
FIRM_API {{attr.type}} get_{{node.name}}_{{attr.name}}(const ir_node *node);
/** Sets {{attr.name}} attribute of {{node.name|a_an}} node. */
FIRM_API void set_{{node.name}}_{{attr.name}}(ir_node *node, {{attr.type}} {{attr.name}});
{% endfor -%}
/** @} */
{% endfor -%}
/** @} */
#include "end.h"
#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.
* @ingroup ir_op
*/
typedef enum {{spec.name}}_opcode {
{%- for node in nodes %}
{{spec.name}}o_{{node.name}},
{%- endfor %}
{{spec.name}}o_First = {{spec.name}}o_{{nodes[0].name}},
{{spec.name}}o_Last = {{spec.name}}o_{{nodes[-1].name}},
{%- if spec.name == "ir" %}
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,
/* last backend node number */
beo_Last = beo_FrameAddr,
{%- endif %}
{{spec.name}}o_MaxOpcode
} {{spec.name}}_opcode;
{% for node in nodes %}
/**
* @ingroup {{node.name}}
* {{node.name}} opcode
*/
FIRM_API ir_op *op_{{node.name}};
{%- endfor %}
{% for node in nodes %}
/**
* @ingroup {{node.name}}
* Returns opcode for {{node.name}} nodes.
*/
FIRM_API ir_op *get_op_{{node.name}}(void);
{%- endfor %}
#endif
''')
#############################
def prepare_nodes(nodes):
real_nodes = []
for node in nodes:
......@@ -756,51 +273,22 @@ def prepare_nodes(nodes):
def main(argv):
if len(argv) < 3:
print "usage: %s specname(ignored) destdirectory" % argv[0]
print "usage: %s specfile templatefile" % argv[0]
sys.exit(1)
specfile = argv[1]
spec = load_spec(specfile)
nodes = spec.nodes
gendir = argv[2]
# hardcoded path to libfirm/include/libfirm
if len(argv) > 3:
gendir2 = argv[3]
else:
gendir2 = argv[2] + "/../../include/libfirm"
specfile = argv[1]
spec = load_spec(specfile)
nodes = spec.nodes
real_nodes = prepare_nodes(nodes)
env.globals['nodes'] = real_nodes
env.globals['spec'] = spec
file = open(gendir + "/gen_ir_cons.c.inl", "w")
file.write(gen_ircons_c_inl_template.render())
file.close()
file = open(gendir + "/gen_irnode.h", "w")
file.write(irnode_h_template.render())
file.close()
file = open(gendir + "/gen_irnode.c.inl", "w")
file.write(irnode_template.render())
file.close()
file = open(gendir + "/gen_irop.c.inl", "w")
file.write(irop_template.render())
file.close()
file = open(gendir + "/gen_irdump.c.inl", "w")
file.write(irdump_template.render())
file.close()
templatefile = argv[2]
file = open(gendir2 + "/opcodes.h", "w")
file.write(opcodes_h_template.render())
file.close()
env.globals['nodes'] = real_nodes
env.globals['spec'] = spec
env.globals['warning'] = "/* Warning: automatically generated file */"
file = open(gendir2 + "/nodeops.h", "w")
file.write(nodeops_h_template.render())
file.close()
template = env.get_template(templatefile)
sys.stdout.write(template.render().encode("utf-8"))
main(sys.argv)
if __name__ == "__main__":
main(sys.argv)
......@@ -3,7 +3,7 @@
# This file is part of libFirm.
# Copyright (C) 2012 Karlsruhe Institute of Technology.