glsl: Generate code for constant binary expressions that combine vector and scalar...
[mesa.git] / src / compiler / glsl / ir_expression_operation.py
1 #! /usr/bin/env python
2 #
3 # Copyright (C) 2015 Intel Corporation
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the "Software"),
7 # to deal in the Software without restriction, including without limitation
8 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 # and/or sell copies of the Software, and to permit persons to whom the
10 # Software is furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice (including the next
13 # paragraph) shall be included in all copies or substantial portions of the
14 # Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 # IN THE SOFTWARE.
23
24 import mako.template
25 import sys
26
27 class type(object):
28 def __init__(self, c_type, union_field, glsl_type):
29 self.c_type = c_type
30 self.union_field = union_field
31 self.glsl_type = glsl_type
32
33
34 class type_signature_iter(object):
35 """Basic iterator for a set of type signatures. Various kinds of sequences of
36 types come in, and an iteration of type_signature objects come out.
37
38 """
39
40 def __init__(self, source_types, num_operands):
41 """Initialize an iterator from a sequence of input types and a number
42 operands. This is for signatures where all the operands have the same
43 type and the result type of the operation is the same as the input type.
44
45 """
46 self.dest_type = None
47 self.source_types = source_types
48 self.num_operands = num_operands
49 self.i = 0
50
51 def __init__(self, dest_type, source_types, num_operands):
52 """Initialize an iterator from a result tpye, a sequence of input types and a
53 number operands. This is for signatures where all the operands have the
54 same type but the result type of the operation is different from the
55 input type.
56
57 """
58 self.dest_type = dest_type
59 self.source_types = source_types
60 self.num_operands = num_operands
61 self.i = 0
62
63 def __iter__(self):
64 return self
65
66 def next(self):
67 if self.i < len(self.source_types):
68 i = self.i
69 self.i += 1
70
71 if self.dest_type is None:
72 dest_type = self.source_types[i]
73 else:
74 dest_type = self.dest_type
75
76 return (dest_type, self.num_operands * (self.source_types[i],))
77 else:
78 raise StopIteration()
79
80
81 uint_type = type("unsigned", "u", "GLSL_TYPE_UINT")
82 int_type = type("int", "i", "GLSL_TYPE_INT")
83 float_type = type("float", "f", "GLSL_TYPE_FLOAT")
84 double_type = type("double", "d", "GLSL_TYPE_DOUBLE")
85 bool_type = type("bool", "b", "GLSL_TYPE_BOOL")
86
87 numeric_types = (uint_type, int_type, float_type, double_type)
88 signed_numeric_types = (int_type, float_type, double_type)
89 integer_types = (uint_type, int_type)
90 real_types = (float_type, double_type)
91
92 # This template is for unary and binary operations that can only have operands
93 # of a single type. ir_unop_logic_not is an example.
94 constant_template0 = mako.template.Template("""\
95 case ${op.get_enum_name()}:
96 assert(op[0]->type->base_type == ${op.source_types[0].glsl_type});
97 for (unsigned c = 0; c < op[0]->type->components(); c++)
98 data.${op.source_types[0].union_field}[c] = ${op.get_c_expression(op.source_types)};
99 break;""")
100
101 # This template is for unary operations that can have operands of a several
102 # different types. ir_unop_bit_not is an example.
103 constant_template1 = mako.template.Template("""\
104 case ${op.get_enum_name()}:
105 switch (op[0]->type->base_type) {
106 % for dst_type, src_types in op.signatures():
107 case ${src_types[0].glsl_type}:
108 for (unsigned c = 0; c < op[0]->type->components(); c++)
109 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
110 break;
111 % endfor
112 default:
113 assert(0);
114 }
115 break;""")
116
117 # This template is for unary operations that can have operands of a several
118 # different types, and each type has a different C expression. ir_unop_neg is
119 # an example.
120 constant_template3 = mako.template.Template("""\
121 case ${op.get_enum_name()}:
122 for (unsigned c = 0; c < op[0]->type->components(); c++) {
123 switch (this->type->base_type) {
124 % for dst_type, src_types in op.signatures():
125 case ${src_types[0].glsl_type}:
126 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
127 break;
128 % endfor
129 default:
130 assert(0);
131 }
132 }
133 break;""")
134
135 # This template is for unary operations that map an operand of one type to an
136 # operand of another type. ir_unop_f2b is an example.
137 constant_template2 = mako.template.Template("""\
138 case ${op.get_enum_name()}:
139 assert(op[0]->type->base_type == ${op.source_types[0].glsl_type});
140 for (unsigned c = 0; c < op[0]->type->components(); c++)
141 data.${op.dest_type.union_field}[c] = ${op.get_c_expression(op.source_types)};
142 break;""")
143
144 # This template is for binary operations that can operate on some combination
145 # of scalar and vector operands.
146 constant_template_vector_scalar = mako.template.Template("""\
147 case ${op.get_enum_name()}:
148 assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
149 for (unsigned c = 0, c0 = 0, c1 = 0;
150 c < components;
151 c0 += c0_inc, c1 += c1_inc, c++) {
152
153 switch (op[0]->type->base_type) {
154 % for dst_type, src_types in op.signatures():
155 case ${src_types[0].glsl_type}:
156 data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1"))};
157 break;
158 % endfor
159 default:
160 assert(0);
161 }
162 }
163 break;""")
164
165
166 vector_scalar_operation = "vector-scalar"
167
168 class operation(object):
169 def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None):
170 self.name = name
171 self.num_operands = num_operands
172
173 if printable_name is None:
174 self.printable_name = name
175 else:
176 self.printable_name = printable_name
177
178 self.source_types = source_types
179 self.dest_type = dest_type
180
181 if c_expression is None:
182 self.c_expression = None
183 elif isinstance(c_expression, str):
184 self.c_expression = {'default': c_expression}
185 else:
186 self.c_expression = c_expression
187
188 if flags is None:
189 self.flags = frozenset()
190 elif isinstance(flags, str):
191 self.flags = frozenset([flags])
192 else:
193 self.flags = frozenset(flags)
194
195
196 def get_enum_name(self):
197 return "ir_{}op_{}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name)
198
199
200 def get_template(self):
201 if self.c_expression is None:
202 return None
203
204 if self.num_operands == 1:
205 if self.dest_type is not None:
206 return constant_template2.render(op=self)
207 elif len(self.source_types) == 1:
208 return constant_template0.render(op=self)
209 elif len(self.c_expression) == 1 and 'default' in self.c_expression:
210 return constant_template1.render(op=self)
211 else:
212 return constant_template3.render(op=self)
213 elif self.num_operands == 2:
214 if vector_scalar_operation in self.flags:
215 return constant_template_vector_scalar.render(op=self)
216 elif len(self.source_types) == 1:
217 return constant_template0.render(op=self)
218
219 return None
220
221
222 def get_c_expression(self, types, indices=("c", "c")):
223 src0 = "op[0]->value.{}[{}]".format(types[0].union_field, indices[0])
224 src1 = "op[1]->value.{}[{}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
225
226 expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default']
227
228 return expr.format(src0=src0,
229 src1=src1)
230
231
232 def signatures(self):
233 return type_signature_iter(self.dest_type, self.source_types, self.num_operands)
234
235
236 ir_expression_operation = [
237 operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
238 operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
239 operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'default': "-{src0}"}),
240 operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})"}),
241 operation("sign", 1, source_types=signed_numeric_types, c_expression={'i': "({src0} > 0) - ({src0} < 0)", 'f': "float(({src0} > 0.0F) - ({src0} < 0.0F))", 'd': "double(({src0} > 0.0) - ({src0} < 0.0))"}),
242 operation("rcp", 1, source_types=real_types, c_expression={'f': "{src0} != 0.0F ? 1.0F / {src0} : 0.0F", 'd': "{src0} != 0.0 ? 1.0 / {src0} : 0.0"}),
243 operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
244 operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
245 operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"), # Log base e on gentype
246 operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"), # Natural log on gentype
247 operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"),
248 operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"),
249
250 # Float-to-integer conversion.
251 operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"),
252 # Float-to-unsigned conversion.
253 operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"),
254 # Integer-to-float conversion.
255 operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"),
256 # Float-to-boolean conversion
257 operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"),
258 # Boolean-to-float conversion
259 operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
260 # int-to-boolean conversion
261 operation("i2b", 1),
262 # Boolean-to-int conversion
263 operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
264 # Unsigned-to-float conversion.
265 operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
266 # Integer-to-unsigned conversion.
267 operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
268 # Unsigned-to-integer conversion.
269 operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
270 # Double-to-float conversion.
271 operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
272 # Float-to-double conversion.
273 operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
274 # Double-to-integer conversion.
275 operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
276 # Integer-to-double conversion.
277 operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
278 # Double-to-unsigned conversion.
279 operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
280 # Unsigned-to-double conversion.
281 operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
282 # Double-to-boolean conversion.
283 operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
284 # 'Bit-identical int-to-float "conversion"
285 operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
286 # 'Bit-identical float-to-int "conversion"
287 operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
288 # 'Bit-identical uint-to-float "conversion"
289 operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
290 # 'Bit-identical float-to-uint "conversion"
291 operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
292
293 # Unary floating-point rounding operations.
294 operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
295 operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
296 operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
297 operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
298 operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
299
300 # Trigonometric operations.
301 operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
302 operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
303
304 # Partial derivatives.
305 operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
306 operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
307 operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
308 operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
309 operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
310 operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
311
312 # Floating point pack and unpack operations.
313 operation("pack_snorm_2x16", 1, printable_name="packSnorm2x16"),
314 operation("pack_snorm_4x8", 1, printable_name="packSnorm4x8"),
315 operation("pack_unorm_2x16", 1, printable_name="packUnorm2x16"),
316 operation("pack_unorm_4x8", 1, printable_name="packUnorm4x8"),
317 operation("pack_half_2x16", 1, printable_name="packHalf2x16"),
318 operation("unpack_snorm_2x16", 1, printable_name="unpackSnorm2x16"),
319 operation("unpack_snorm_4x8", 1, printable_name="unpackSnorm4x8"),
320 operation("unpack_unorm_2x16", 1, printable_name="unpackUnorm2x16"),
321 operation("unpack_unorm_4x8", 1, printable_name="unpackUnorm4x8"),
322 operation("unpack_half_2x16", 1, printable_name="unpackHalf2x16"),
323
324 # Bit operations, part of ARB_gpu_shader5.
325 operation("bitfield_reverse", 1, source_types=integer_types, c_expression="bitfield_reverse({src0})"),
326 operation("bit_count", 1),
327 operation("find_msb", 1),
328 operation("find_lsb", 1),
329
330 operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
331
332 # Double packing, part of ARB_gpu_shader_fp64.
333 operation("pack_double_2x32", 1, printable_name="packDouble2x32"),
334 operation("unpack_double_2x32", 1, printable_name="unpackDouble2x32"),
335
336 operation("frexp_sig", 1),
337 operation("frexp_exp", 1),
338
339 operation("noise", 1),
340
341 operation("subroutine_to_int", 1),
342
343 # Interpolate fs input at centroid
344 #
345 # operand0 is the fs input.
346 operation("interpolate_at_centroid", 1),
347
348 # Ask the driver for the total size of a buffer block.
349 # operand0 is the ir_constant buffer block index in the linked shader.
350 operation("get_buffer_size", 1),
351
352 # Calculate length of an unsized array inside a buffer block.
353 # This opcode is going to be replaced in a lowering pass inside
354 # the linker.
355 #
356 # operand0 is the unsized array's ir_value for the calculation
357 # of its length.
358 operation("ssbo_unsized_array_length", 1),
359
360 # Vote among threads on the value of the boolean argument.
361 operation("vote_any", 1),
362 operation("vote_all", 1),
363 operation("vote_eq", 1),
364
365 operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
366 operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
367 # "Floating-point or low 32-bit integer multiply."
368 operation("mul", 2, printable_name="*"),
369 operation("imul_high", 2), # Calculates the high 32-bits of a 64-bit multiply.
370 operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
371
372 # Returns the carry resulting from the addition of the two arguments.
373 operation("carry", 2),
374
375 # Returns the borrow resulting from the subtraction of the second argument
376 # from the first argument.
377 operation("borrow", 2),
378
379 # Either (vector % vector) or (vector % scalar)
380 #
381 # We don't use fmod because it rounds toward zero; GLSL specifies the use
382 # of floor.
383 operation("mod", 2, printable_name="%", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} % {src1}", 'i': "{src1} == 0 ? 0 : {src0} % {src1}", 'f': "{src0} - {src1} * floorf({src0} / {src1})", 'd': "{src0} - {src1} * floor({src0} / {src1})"}, flags=vector_scalar_operation),
384
385 # Binary comparison operators which return a boolean vector.
386 # The type of both operands must be equal.
387 operation("less", 2, printable_name="<"),
388 operation("greater", 2, printable_name=">"),
389 operation("lequal", 2, printable_name="<="),
390 operation("gequal", 2, printable_name=">="),
391 operation("equal", 2, printable_name="=="),
392 operation("nequal", 2, printable_name="!="),
393
394 # Returns single boolean for whether all components of operands[0]
395 # equal the components of operands[1].
396 operation("all_equal", 2),
397
398 # Returns single boolean for whether any component of operands[0]
399 # is not equal to the corresponding component of operands[1].
400 operation("any_nequal", 2),
401
402 # Bit-wise binary operations.
403 operation("lshift", 2, printable_name="<<"),
404 operation("rshift", 2, printable_name=">>"),
405 operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
406 operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
407 operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
408
409 operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
410 operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
411 operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
412
413 operation("dot", 2),
414 operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
415 operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
416
417 operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
418
419 # Load a value the size of a given GLSL type from a uniform block.
420 #
421 # operand0 is the ir_constant uniform block index in the linked shader.
422 # operand1 is a byte offset within the uniform block.
423 operation("ubo_load", 2),
424
425 # Multiplies a number by two to a power, part of ARB_gpu_shader5.
426 operation("ldexp", 2),
427
428 # Extract a scalar from a vector
429 #
430 # operand0 is the vector
431 # operand1 is the index of the field to read from operand0
432 operation("vector_extract", 2),
433
434 # Interpolate fs input at offset
435 #
436 # operand0 is the fs input
437 # operand1 is the offset from the pixel center
438 operation("interpolate_at_offset", 2),
439
440 # Interpolate fs input at sample position
441 #
442 # operand0 is the fs input
443 # operand1 is the sample ID
444 operation("interpolate_at_sample", 2),
445
446 # Fused floating-point multiply-add, part of ARB_gpu_shader5.
447 operation("fma", 3),
448
449 operation("lrp", 3),
450
451 # Conditional Select
452 #
453 # A vector conditional select instruction (like ?:, but operating per-
454 # component on vectors).
455 #
456 # See also lower_instructions_visitor::ldexp_to_arith
457 operation("csel", 3),
458
459 operation("bitfield_extract", 3),
460
461 # Generate a value with one field of a vector changed
462 #
463 # operand0 is the vector
464 # operand1 is the value to write into the vector result
465 # operand2 is the index in operand0 to be modified
466 operation("vector_insert", 3),
467
468 operation("bitfield_insert", 4),
469
470 operation("vector", 4),
471 ]
472
473
474 if __name__ == "__main__":
475 copyright = """/*
476 * Copyright (C) 2010 Intel Corporation
477 *
478 * Permission is hereby granted, free of charge, to any person obtaining a
479 * copy of this software and associated documentation files (the "Software"),
480 * to deal in the Software without restriction, including without limitation
481 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
482 * and/or sell copies of the Software, and to permit persons to whom the
483 * Software is furnished to do so, subject to the following conditions:
484 *
485 * The above copyright notice and this permission notice (including the next
486 * paragraph) shall be included in all copies or substantial portions of the
487 * Software.
488 *
489 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
490 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
491 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
492 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
493 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
494 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
495 * DEALINGS IN THE SOFTWARE.
496 */
497 """
498 enum_template = mako.template.Template(copyright + """
499 enum ir_expression_operation {
500 % for item in values:
501 ${item.get_enum_name()},
502 % endfor
503
504 /* Sentinels marking the last of each kind of operation. */
505 % for item in lasts:
506 ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
507 % endfor
508 ir_last_opcode = ir_quadop_${lasts[3].name}
509 };""")
510
511 strings_template = mako.template.Template(copyright + """
512 const char *const ir_expression_operation_strings[] = {
513 % for item in values:
514 "${item.printable_name}",
515 % endfor
516 };""")
517
518 constant_template = mako.template.Template("""\
519 switch (this->operation) {
520 % for op in values:
521 % if op.c_expression is not None:
522 ${op.get_template()}
523
524 % endif
525 % endfor
526 default:
527 /* FINISHME: Should handle all expression types. */
528 return NULL;
529 }
530 """)
531
532 if sys.argv[1] == "enum":
533 lasts = [None, None, None, None]
534 for item in reversed(ir_expression_operation):
535 i = item.num_operands - 1
536 if lasts[i] is None:
537 lasts[i] = item
538
539 print(enum_template.render(values=ir_expression_operation,
540 lasts=lasts))
541 elif sys.argv[1] == "strings":
542 print(strings_template.render(values=ir_expression_operation))
543 elif sys.argv[1] == "constant":
544 print(constant_template.render(values=ir_expression_operation))