gen_ir.py 15.5 KB
Newer Older
1
2
#!/usr/bin/env python
import sys
3
import re
4
5
from jinja2 import Environment, Template
from jinja2.filters import do_dictsort
6
from spec_util import is_dynamic_pinned, verify_node, isAbstract, setdefault
7
from ir_spec import nodes
8

9
10
def format_parameterlist(parameterlist):
	return "\n".join(parameterlist)
11

12
def format_nodearguments(node):
13
	arguments = map(lambda arg: arg["name"], node.arguments)
14
	return format_parameterlist(arguments)
15

16
17
18
19
def format_nodeparameters(node):
	parameters = map(lambda arg: arg["type"] + " " + arg["name"], node.arguments)
	return format_parameterlist(parameters)

20
21
22
23
24
25
26
27
28
29
30
def format_nodeparametershelp(node):
	res = ""
	for param in node.arguments:
		res += " * @param %-9s %s\n" % (param["name"], param["comment"])
	return res

def format_a_an(text):
	if text[0] in "aAeEuUoOiI":
		return "an " + text
	return "a " + text

31
def format_blockparameter(node):
32
	if hasattr(node, "knownBlock"):
33
34
		if hasattr(node, "knownGraph"):
			return ""
35
36
37
38
		return "ir_graph *irg"
	else:
		return "ir_node *block"

39
40
41
42
43
44
45
46
def format_blockparameterhelp(node):
	if hasattr(node, "knownBlock"):
		if hasattr(node, "knownGraph"):
			return ""
		return " * @param irg       The IR graph the node belongs to.\n"
	else:
		return " * @param block     The IR block the node belongs to.\n"

47
def format_blockargument(node):
48
	if hasattr(node, "knownBlock"):
49
50
51
		if hasattr(node, "knownGraph"):
			return ""
		return "irg"
52
	else:
53
54
55
56
57
		return "block"

def format_irgassign(node):
	if hasattr(node, "knownGraph"):
		return "ir_graph *irg = %s;\n" % node.graph
58

59
	if hasattr(node, "knownBlock"):
60
		return ""
61
	else:
62
		return "ir_graph *irg = get_Block_irg(block);\n"
63
64

def format_curblock(node):
65
	if hasattr(node, "knownBlock"):
66
67
		if hasattr(node, "knownGraph"):
			return ""
68
		return "current_ir_graph"
69
	else:
70
		return "current_ir_graph->current_block"
71
72

def format_insdecl(node):
73
74
	arity = node.arity
	if arity == "variable" and len(node.ins) == 0 or arity == "dynamic" or arity == 0:
75
76
77
		return ""

	if arity == "variable":
78
		insarity = len(node.ins)
79
80
81
		res  = "int r_arity = arity + " + `insarity` + ";"
		res += "\n\tir_node **r_in;"
		res += "\n\tNEW_ARR_A(ir_node *, r_in, r_arity);"
82
		i = 0
83
		for input in node.ins:
84
			res += "\n\tr_in[" + `i` + "] = irn_" + input[0] + ";"
85
			i += 1
86
		res += "\n\tmemcpy(&r_in[" + `insarity` + "], in, sizeof(ir_node *) * arity);\n\t"
87
	else:
88
		res = "ir_node *in[" + `arity` + "];"
89
		i = 0
90
		for input in node.ins:
91
			res += "\n\tin[" + `i` + "] = irn_" + input[0] + ";"
92
93
94
95
			i += 1
	return res

def format_arity_and_ins(node):
96
	arity = node.arity
97
98
99
	if arity == "dynamic":
		return "-1, NULL"
	elif arity == "variable":
100
		if len(node.ins) == 0:
101
102
103
104
105
106
107
108
			return "arity, in"
		else:
			return "r_arity, r_in"
	elif arity == 0:
		return "0, NULL"
	else:
		return `arity` + ", in"

109
def format_arity(node):
110
111
112
	if hasattr(node, "arity_override"):
		return node.arity_override
	arity = node.arity
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	if arity == "dynamic":
		return "oparity_dynamic"
	if arity == "variable":
		return "oparity_variable"
	if arity == 0:
		return "oparity_zero"
	if arity == 1:
		return "oparity_unary"
	if arity == 2:
		return "oparity_binary"
	if arity == 3:
		return "oparity_trinary"
	return "oparity_any"

def format_pinned(node):
128
	pinned = node.pinned
129
130
131
132
133
134
135
136
137
138
139
140
	if pinned == "yes":
		return "op_pin_state_pinned"
	if pinned == "no":
		return "op_pin_state_floats"
	if pinned == "exception":
		return "op_pin_state_exc_pinned"
	if pinned == "memory":
		return "op_pin_state_mem_pinned"
	print "WARNING: Unknown pinned state %s in format pined" % pinned
	return ""

def format_flags(node):
141
142
143
	flags = map(lambda x : "irop_flag_" + x, node.flags)
	if flags == []:
		flags = [ "irop_flag_none" ]
144
145
146
	return " | ".join(flags)

def format_attr_size(node):
147
	if not hasattr(node, "attr_struct"):
148
		return "0"
149
	return "sizeof(%s)" % node.attr_struct
150

151
def format_opindex(node):
152
153
	if hasattr(node, "op_index"):
		return node.op_index
154
155
	return "-1"

156
157
158
159
160
161
keywords = frozenset([ "true", "false" ])
def format_escape_keywords(word):
	if word in keywords:
		return word + "_"
	return word

162
def filter_isnot(list, flag):
163
164
165
166
	return filter(lambda x: not hasattr(x, flag), list)

def filter_hasnot(list, flag):
	return filter(lambda x: flag not in x, list)
167

168
169
170
171
172
173
174
175
176
177
178
179
180
def format_arguments(string, voidwhenempty = False):
	args = re.split('\s*\n\s*', string)
	if args[0] == '':
		args = args[1:]
	if len(args) > 0 and args[-1] == '':
		args = args[:-1]
	if len(args) == 0 and voidwhenempty:
		return "void"
	return ", ".join(args)

def format_parameters(string):
	return format_arguments(string, voidwhenempty = True)

181
env = Environment()
182
env.filters['a_an']            = format_a_an
183
184
185
env.filters['parameterlist']   = format_parameterlist
env.filters['nodearguments']   = format_nodearguments
env.filters['nodeparameters']  = format_nodeparameters
186
env.filters['nodeparametershelp'] = format_nodeparametershelp
187
env.filters['blockparameter']  = format_blockparameter
188
env.filters['blockparameterhelp'] = format_blockparameterhelp
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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
204
205
206

def prepare_attr(attr):
	if "init" in attr:
207
208
209
210
211
		return dict(
			type = attr["type"],
			name = attr["name"],
			init = attr["init"],
			comment = attr["comment"])
212
	else:
213
214
215
216
		return dict(
			type = attr["type"],
			name = attr["name"],
			comment = attr["comment"])
217

218
219
220
221
222
def preprocess_node(node):
	verify_node(node)

	setdefault(node, "attrs_name", node.name.lower())
	setdefault(node, "block", "block")
223

224
225
226
	# construct node arguments
	arguments = [ ]
	initattrs = [ ]
227
	for input in node.ins:
228
229
230
231
		arguments.append(dict(
				type    = "ir_node *",
				name    = "irn_" + input[0],
				comment = input[1]))
232

233
	if node.arity == "variable" or node.arity == "dynamic":
234
235
236
237
238
		arguments.append(dict(
				type    = "int",
				name    = "arity",
				comment = "size of additional inputs array"))
		arguments.append(dict(
239
				type    = "ir_node *const *",
240
241
				name    = "in",
				comment = "additional inputs"))
242

243
	if not hasattr(node, "mode"):
244
245
246
247
		arguments.append(dict(
				type    = "ir_mode *",
				name    = "mode",
				comment = "mode of the operations result"))
248
		node.mode = "mode"
249

250
	for attr in node.attrs:
251
		attr["fqname"] = "." + attr["name"]
252
253
254
		if "init" in attr:
			continue
		arguments.append(attr)
255

256
257
	# dynamic pin state means more constructor arguments
	if is_dynamic_pinned(node):
258
		if hasattr(node, "pinned_init"):
259
			initattrs.append(dict(
260
261
				fqname = ".exc.pin_state",
				init   = node.pinned_init
262
263
			))
		else:
264
			node.constructor_args.append(
265
				dict(
266
267
268
					name    = "pin_state",
					type    = "op_pin_state",
					comment = "pinned state",
269
270
271
				)
			)
			initattrs.append(dict(
272
273
				fqname = ".exc.pin_state",
				init   = "pin_state"
274
275
			))

276
	for arg in node.constructor_args:
277
278
		arguments.append(prepare_attr(arg))

279
280
	node.arguments = arguments
	node.initattrs = initattrs
281
282
283

#############################

284
285
gen_ircons_c_inl_template = env.from_string(
'''/* Warning: automatically generated code */
286

287
288
{%- for node in nodes %}
{%- if not node.noconstructor %}
289
ir_node *new_rd_{{node.name}}(
290
291
292
293
294
	{%- filter parameters %}
		dbg_info *dbgi
		{{node|blockparameter}}
		{{node|nodeparameters}}
	{% endfilter %})
295
296
{
	ir_node *res;
297
298
299
	{%- if node.arity == "dynamic" %}
	int      i;
	{%- endif %}
300
	{{node|irgassign}}
301
	{{node|insdecl}}
302

303
304
305
306
307
308
309
310
311
	res = new_ir_node(
		{%- filter arguments %}
			dbgi
			irg
			{{node.block}}
			op_{{node.name}}
			{{node.mode}}
			{{node|arity_and_ins}}
		{% endfilter %});
312
313
314
315
316
	{%- if node.arity == "dynamic" %}
	for (i = 0; i < arity; ++i) {
		add_irn_n(res, in[i]);
	}
	{%- endif %}
317
	{%- for attr in node.attrs %}
318
	res->attr.{{node.attrs_name}}{{attr["fqname"]}} =
319
320
		{%- if "init" in attr %} {{ attr["init"] -}};
		{%- else              %} {{ attr["name"] -}};
321
322
323
		{%- endif %}
	{%- endfor %}
	{%- for attr in node.initattrs %}
324
	res->attr.{{node.attrs_name}}{{attr["fqname"]}} = {{ attr["init"] -}};
325
	{%- endfor %}
326
	{{- node.init }}
327
	res = optimize_node(res);
328
	irn_verify_irg(res, irg);
329
	{{- node.init_after_opt }}
330
331
332
	return res;
}

333
ir_node *new_r_{{node.name}}(
334
335
336
337
		{%- filter parameters %}
			{{node|blockparameter}}
			{{node|nodeparameters}}
		{% endfilter %})
338
{
339
	return new_rd_{{node.name}}(
340
341
342
343
344
		{%- filter arguments %}
			NULL
			{{node|blockargument}}
			{{node|nodearguments}}
		{% endfilter %});
345
346
}

347
ir_node *new_d_{{node.name}}(
348
349
350
351
		{%- filter parameters %}
			dbg_info *dbgi
			{{node|nodeparameters}}
		{% endfilter %})
352
353
{
	ir_node *res;
354
	assert(get_irg_phase_state(current_ir_graph) == phase_building);
355
	res = new_rd_{{node.name}}(
356
357
358
359
360
		{%- filter parameters %}
			dbgi
			{{node|curblock}}
			{{node|nodearguments}}
		{% endfilter %});
361
362
363
	return res;
}

364
ir_node *new_{{node.name}}(
365
366
367
		{%- filter parameters %}
			{{node|nodeparameters}}
		{% endfilter %})
Moritz Kroll's avatar
Moritz Kroll committed
368
{
369
	return new_d_{{node.name}}(
370
371
372
373
		{%- filter arguments %}
			NULL
			{{node|nodearguments}}
		{% endfilter %});
Moritz Kroll's avatar
Moritz Kroll committed
374
}
375
376
{% endif %}
{%- endfor %}
377
378
''')

379
380
irnode_h_template = env.from_string(
'''/* Warning: automatically generated code */
381

382
{%- for node in nodes|isnot('custom_is') %}
383
static inline int _is_{{node.name}}(const ir_node *node)
384
385
{
	assert(node != NULL);
386
	return _get_irn_op(node) == op_{{node.name}};
387
}
388
{%- endfor -%}
389

390
391
{% for node in nodes %}
#define is_{{node.name}}(node)    _is_{{node.name}}(node)
392
{%- endfor %}
393

394
395
''')

396
397
irnode_template = env.from_string(
'''/* Warning: automatically generated code */
398
399
{% for node in nodes %}
int (is_{{node.name}})(const ir_node *node)
400
{
401
	return _is_{{node.name}}(node);
402
403
}
{% endfor %}
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422

{%- for node in nodes %}
{%- for attr in node.attrs|hasnot("noprop") %}
{{attr.type}} (get_{{node.name}}_{{attr.name}})(const ir_node *node)
{
	assert(is_{{node.name}}(node));
	return node->attr.{{node.attrs_name}}.{{attr.name}};
}

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 -%}
{% endfor -%}

{%- for node in nodes %}
{%- for in in node.ins %}
423
ir_node *(get_{{node.name}}_{{in[0]}})(const ir_node *node)
424
425
426
427
428
{
	assert(is_{{node.name}}(node));
	return get_irn_n(node, {{node.ins.index(in)}});
}

429
void (set_{{node.name}}_{{in[0]}})(ir_node *node, ir_node *{{in[0]|escape_keywords}})
430
431
{
	assert(is_{{node.name}}(node));
432
	set_irn_n(node, {{node.ins.index(in)}}, {{in[0]|escape_keywords}});
433
434
435
}
{% endfor %}
{% endfor %}
436
437
''')

438
439
irop_template = env.from_string(
'''/* Warning: automatically generated code */
440
441
{% for node in nodes %}
ir_op *op_{{node.name}}; ir_op *get_op_{{node.name}}(void) { return op_{{node.name}}; }
442
{%- endfor %}
Moritz Kroll's avatar
Moritz Kroll committed
443

444
445
void init_op(void)
{
446
	{% for node in nodes %}
447
448
449
450
451
452
453
454
455
456
457
	op_{{node.name}} = new_ir_op(
		{%- filter arguments %}
			iro_{{node.name}}
			"{{node.name}}"
			{{node|pinned}}
			{{node|flags}}
			{{node|arity}}
			{{node|opindex}}
			{{node|attr_size}}
			NULL
		{% endfilter %});
458
459
460
461
462
463
464
	{%- endfor %}

	be_init_op();
}

void finish_op(void)
{
465
466
	{% for node in nodes %}
	free_ir_op(op_{{node.name}}); op_{{node.name}} = NULL;
467
468
	{%- endfor %}
}
469

470
471
''')

472
473
nodeops_h_template = env.from_string(
'''/* Warning: automatically generated code */
474
475
476
477
478
479
480
481
482
#ifndef FIRM_IR_NODEOPS_H
#define FIRM_IR_NODEOPS_H

#include "firm_types.h"

/**
 * @addtogroup ir_node
 * @{
 */
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498

{% for node in nodes -%}
{% 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}};
{% endif %}
{%- endfor %}

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
{% for node in nodes %}
{%- 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 %}
{% endfor %}

551
552
553
554
555
556
557
{% 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 -%}
558
559
FIRM_API ir_node *get_{{node.name}}_{{in[0]}}(const ir_node *node);
void set_{{node.name}}_{{in[0]}}(ir_node *node, ir_node *{{in[0]|escape_keywords}});
560
561
562
563
564
565
566
567
568
569
{% 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
570

571
572
''')

573
574
opcodes_h_template = env.from_string(
'''/* Warning: automatically generated code */
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
#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,
	/* last backend node number */
603
	beo_Last = beo_FrameAddr,
604
605
606
607
608
609
610
611
612
613
614
615
	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
616

617
618
''')

619
620
#############################

621
622
623
624
625
626
627
628
629
630
631
632
def prepare_nodes():
	real_nodes = []
	for node in nodes:
		if isAbstract(node):
			continue
		real_nodes.append(node)

	for node in real_nodes:
		preprocess_node(node)

	return real_nodes

633
634
635
636
637
638
def main(argv):
	if len(argv) < 3:
		print "usage: %s specname(ignored) destdirectory" % argv[0]
		sys.exit(1)

	gendir = argv[2]
639
640
	# hardcoded path to libfirm/include/libfirm
	gendir2 = argv[2] + "/../../include/libfirm"
641

642
	real_nodes = prepare_nodes()
643

644
645
	file = open(gendir + "/gen_ir_cons.c.inl", "w")
	file.write(gen_ircons_c_inl_template.render(nodes = real_nodes))
646
647
	file.close()

648
649
650
651
652
653
654
655
656
657
658
659
	file = open(gendir + "/gen_irnode.h", "w")
	file.write(irnode_h_template.render(nodes = real_nodes))
	file.close()

	file = open(gendir + "/gen_irnode.c.inl", "w")
	file.write(irnode_template.render(nodes = real_nodes))
	file.close()

	file = open(gendir + "/gen_irop.c.inl", "w")
	file.write(irop_template.render(nodes = real_nodes))
	file.close()

660
661
662
663
	file = open(gendir2 + "/opcodes.h", "w")
	file.write(opcodes_h_template.render(nodes = real_nodes))
	file.close()

664
665
666
667
	file = open(gendir2 + "/nodeops.h", "w")
	file.write(nodeops_h_template.render(nodes = real_nodes))
	file.close()

668
main(sys.argv)