gen_ir_io.py 8.1 KB
Newer Older
Christoph Mallon's avatar
Christoph Mallon committed
1
#!/usr/bin/env python
2
3
import sys
from jinja2 import Environment, Template
4
from jinja2.filters import do_dictsort
5
from spec_util import is_dynamic_pinned, verify_node
6
7
import ir_spec

8
9
10
11
12
13
14
15
def error(msg):
	"""writes an error message to stderr"""
	sys.stderr.write("Error: " + msg + "\n");

def warning(msg):
	"""writes a warning message to stderr"""
	sys.stderr.write("Warning: " + msg + "\n");

16
17
18
19
20
def format_args(arglist):
	#argstrings = map(lambda arg : arg["name"], arglist)
	#return ", ".join(argstrings)
	s = ", ".join(arglist)
	if len(s) == 0:
21
22
	  return ""
	return ", " + s
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

def format_ifnset(string, node, key):
	if key in node:
		return ""
	return string

def format_block(node):
	if node.get("knownBlock"):
		return ""
	else:
		return ", get_node(env, preds[0])"

env = Environment()
env.filters['args']   = format_args
env.filters['ifnset'] = format_ifnset
env.filters['block']  = format_block

def get_io_type(type, attrname, nodename):
	if type == "tarval*":
		importcmd = "tarval *%s = read_tv(env);" % attrname
43
		exportcmd = "write_tarval(env, %(val)s);";
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
	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));"""
	elif type == "ir_type*":
		importcmd = "ir_type *%s = read_type(env);" % attrname
		exportcmd = """fprintf(env->file, "%%ld ", get_type_nr(%(val)s));"""
	elif type == "long" and nodename == "Proj":
		importcmd = "long %s = read_long(env);" % attrname
		exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
	elif type == "pn_Cmp" or type == "ir_where_alloc":
		importcmd = "%s %s = (%s) read_long(env);" % (type, attrname, type)
		exportcmd = """fprintf(env->file, "%%ld ", (long) %(val)s);"""
Moritz Kroll's avatar
Moritz Kroll committed
59
	elif type == "ir_cons_flags" and nodename == "Store":
60
61
		importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
		exportcmd = """write_pin_state(env, irn);
62
63
			write_volatility(env, irn);
			write_align(env, irn);"""
Moritz Kroll's avatar
Moritz Kroll committed
64
	elif type == "ir_cons_flags" and nodename == "Load":
65
66
		importcmd = "ir_cons_flags %s = get_cons_flags(env);" % attrname
		exportcmd = """write_pin_state(env, irn);
67
68
			write_volatility(env, irn);
			write_align(env, irn);"""
69
70
71
	elif type == "op_pin_state":
		importcmd = "op_pin_state %s = read_pin_state(env);" % attrname
		exportcmd = "write_pin_state(env, irn);"
72
73
74
	elif type == "ir_builtin_kind":
		importcmd = "ir_builtin_kind %s = read_builtin_kind(env);" % attrname
		exportcmd = "write_builtin_kind(env, irn);"
75
76
77
78
79
80
	elif type == "cond_kind":
		importcmd = "cond_kind %s = read_cond_kind(env);" % attrname
		exportcmd = "write_cond_kind(env, irn);"
	elif type == "cond_jmp_predicate":
		importcmd = "cond_jmp_predicate %s = read_cond_jmp_predicate(env);" % attrname
		exportcmd = "write_cond_jmp_predicate(env, irn);"
81
82
83
	elif type == "int":
		importcmd = "int %s = (int) read_long(env);" % attrname
		exportcmd = """fprintf(env->file, "%%d ", %(val)s);"""
84
85
86
	elif type == "long":
		importcmd = "long %s = read_long(env);" % attrname
		exportcmd = """fprintf(env->file, "%%ld ", %(val)s);"""
87
	else:
88
		error("cannot generate import/export for node %s: unsupported attribute type: %s" % (nodename, type))
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
		importcmd = """// BAD: %s %s
			%s %s = (%s) 0;""" % (type, attrname, type, attrname, type)
		exportcmd = "// BAD: %s" % type
	return (importcmd, exportcmd)

def prepare_attr(nodename, attr):
	(importcmd,exportcmd) = get_io_type(attr["type"], attr["name"], nodename)
	attr["importcmd"] = importcmd
	attr["exportcmd"] = exportcmd % {"val": "get_%s_%s(irn)" % (nodename, attr["name"])}

def preprocess_node(nodename, node):
	if "is_a" in node:
		parent = ir_spec.nodes[node["is_a"]]
		node["ins"] = parent["ins"]
		if "outs" in parent:
			node["outs"] = parent["outs"]
	if "ins" not in node:
		node["ins"] = []
	if "outs" in node:
		node["mode"] = "mode_T"
	if "arity" not in node:
		node["arity"] = len(node["ins"])
	if "attrs" not in node:
		node["attrs"] = []
	if "constructor_args" not in node:
		node["constructor_args"] = []
115
116
117
118
119
120
121
122
123
124
125
126
	if "pinned" not in node:
		node["pinned"] = "no"
	# dynamic pin state means, we have to im/export that
	if is_dynamic_pinned(node):
		newattr = dict(
			name = "state",
			type = "op_pin_state"
		)
		if "pinned_init" in node:
			newattr["init"] = node["pinned_init"]
		node["attrs"].append(newattr)

127
	verify_node(nodename, node)
128
129
130

	# construct node arguments
	arguments = [ ]
131
	initargs = [ ]
132
	specialconstrs = [ ]
133
134
135
136
137
138
139
140
141
142
143
144
	i = 0
	for input in node["ins"]:
		arguments.append("prednodes[%i]" % i)
		i += 1

	if node["arity"] == "variable" or node["arity"] == "dynamic":
		arguments.append("numpreds - %i" % (i + 1))
		arguments.append("prednodes + %i" % i)

	if "mode" not in node:
		arguments.append("mode")

145
	attrs_with_special = 0
146
147
	for attr in node["attrs"]:
		prepare_attr(nodename, attr)
148
149
		if "special" in attr:
			if not "init" in attr:
150
				warning("Node type %s has an attribute with a \"special\" entry but without \"init\"" % nodename)
151
152
153
				sys.exit(1)

			if attrs_with_special != 0:
154
				warning("Node type %s has more than one attribute with a \"special\" entry" % nodename)
155
156
157
158
159
160
161
162
163
				sys.exit(1)

			attrs_with_special += 1

			if "prefix" in attr["special"]:
				specialname = attr["special"]["prefix"] + nodename
			elif "suffix" in attr["special"]:
				specialname = nodename + attr["special"]["suffix"]
			else:
164
				error("Unknown special constructor type for node type %s" % nodename)
165
166
167
168
169
170
171
172
173
174
				sys.exit(1)

			specialconstrs.append(
				dict(
					constrname = specialname,
					attrname = attr["name"],
					value = attr["special"]["init"]
				)
			)
		elif "init" in attr:
175
176
177
178
179
			if attr["type"] == "op_pin_state":
				initfunc = "set_irn_pinned"
			else:
				initfunc = "set_" + nodename + "_" + attr["name"]
			initargs.append((attr["name"], initfunc))
180
181
		else:
			arguments.append(attr["name"])
182
183
184
185
186
187

	for arg in node["constructor_args"]:
		prepare_attr(nodename, arg)
		arguments.append(arg["name"])

	node["arguments"] = arguments
188
	node["initargs"] = initargs
189
	node["special_constructors"] = specialconstrs
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205

export_attrs_template = env.from_string('''
	case iro_{{nodename}}:
		{{"write_mode(env, get_irn_mode(irn));"|ifnset(node,"mode")}}
		{% for attr in node.attrs %}{{attr.exportcmd}}
		{% endfor %}
		{% for attr in node.constructor_args %}{{attr.exportcmd}}
		{% endfor %}break;''')

import_attrs_template = env.from_string('''
	case iro_{{nodename}}:
	{
		{{"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}}
206
207
208
209
210
		{% endfor %}
		{% for special in node.special_constructors %}if({{special.attrname}} == {{special.value}})
			newnode = new_r_{{special.constrname}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
		else{% endfor %}
		newnode = new_r_{{nodename}}(current_ir_graph{{node|block}}{{node["arguments"]|args}});
211
		{% for (initarg, initfunc) in node.initargs %}{{initfunc}}(newnode, {{initarg}});
212
		{% endfor %}
213
214
215
216
217
218
219
		break;
	}
''')

def main(argv):
	"""the main function"""

Moritz Kroll's avatar
Moritz Kroll committed
220
221
	if len(argv) < 3:
		print "usage: %s specname(ignored) destdirectory" % argv[0]
222
223
		sys.exit(1)

Moritz Kroll's avatar
Moritz Kroll committed
224
	gendir = argv[2]
225
	sortednodes = do_dictsort(ir_spec.nodes)
226
227
228
229
	# 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" ]
230

231
	file = open(gendir + "/gen_irio_export.inl", "w");
232
	for nodename, node in sortednodes:
233
234
235
		if nodename in niynodes:
			continue

236
		preprocess_node(nodename, node)
237
		if "abstract" not in node:
238
239
240
241
242
			file.write(export_attrs_template.render(vars()))
	file.write("\n")
	file.close()

	file = open(gendir + "/gen_irio_import.inl", "w");
243
	for nodename, node in sortednodes:
244
245
246
		if "abstract" in node or nodename in customcode or nodename in niynodes:
			continue
		file.write(import_attrs_template.render(vars()))
247
248
249
250
	file.write("\n")
	file.close()

	file = open(gendir + "/gen_irio_lex.inl", "w");
251
	for nodename, node in sortednodes:
252
		if "abstract" not in node and nodename not in niynodes:
253
254
255
256
257
			file.write("\tINSERT(\"" + nodename + "\", tt_iro, iro_" + nodename + ");\n");
	file.close()

if __name__ == "__main__":
	main(sys.argv)