xref: /aosp_15_r20/external/mesa3d/src/compiler/glsl/ir_expression_operation.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1#
2# Copyright (C) 2015 Intel Corporation
3#
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the "Software"),
6# to deal in the Software without restriction, including without limitation
7# the rights to use, copy, modify, merge, publish, distribute, sublicense,
8# and/or sell copies of the Software, and to permit persons to whom the
9# Software is furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice (including the next
12# paragraph) shall be included in all copies or substantial portions of the
13# Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21# IN THE SOFTWARE.
22
23import mako.template
24import sys
25import itertools
26
27class 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
34class 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   next = __next__
81
82
83uint_type = type("unsigned", "u", "GLSL_TYPE_UINT")
84int_type = type("int", "i", "GLSL_TYPE_INT")
85uint64_type = type("uint64_t", "u64", "GLSL_TYPE_UINT64")
86int64_type = type("int64_t", "i64", "GLSL_TYPE_INT64")
87float_type = type("float", "f", "GLSL_TYPE_FLOAT")
88double_type = type("double", "d", "GLSL_TYPE_DOUBLE")
89bool_type = type("bool", "b", "GLSL_TYPE_BOOL")
90
91all_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type, bool_type)
92numeric_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type)
93signed_numeric_types = (int_type, float_type, double_type, int64_type)
94integer_types = (uint_type, int_type, uint64_type, int64_type)
95real_types = (float_type, double_type)
96
97# This template is for operations that can have operands of a several
98# different types, and each type may or may not has a different C expression.
99# This is used by most operations.
100constant_template_common = mako.template.Template("""\
101   case ${op.get_enum_name()}:
102      for (unsigned c = 0; c < glsl_get_components(op[0]->type); c++) {
103         switch (op[0]->type->base_type) {
104    % for dst_type, src_types in op.signatures():
105         case ${src_types[0].glsl_type}:
106            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
107            break;
108    % endfor
109         default:
110            unreachable("invalid type");
111         }
112      }
113      break;""")
114
115# This template is for binary operations that can operate on some combination
116# of scalar and vector operands where both source types are the same.
117constant_template_vector_scalar = mako.template.Template("""\
118   case ${op.get_enum_name()}:
119      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
120      for (unsigned c = 0, c0 = 0, c1 = 0;
121           c < components;
122           c0 += c0_inc, c1 += c1_inc, c++) {
123
124         switch (op[0]->type->base_type) {
125    % for dst_type, src_types in op.signatures():
126         case ${src_types[0].glsl_type}:
127            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
128            break;
129    % endfor
130         default:
131            unreachable("invalid type");
132         }
133      }
134      break;""")
135
136# This template is for binary operations that can operate on some combination
137# of scalar and vector operands where the source types can be mixed.
138constant_template_vector_scalar_mixed = mako.template.Template("""\
139   case ${op.get_enum_name()}:
140        % for i in range(op.num_operands):
141      assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
142            % for src_type in op.source_types[1:-1]:
143             op[${i}]->type->base_type == ${src_type.glsl_type} ||
144            % endfor
145             op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
146        % endfor
147      for (unsigned c = 0, c0 = 0, c1 = 0;
148           c < components;
149           c0 += c0_inc, c1 += c1_inc, c++) {
150         <%
151           first_sig_dst_type, first_sig_src_types = op.signatures()[0]
152           last_sig_dst_type, last_sig_src_types = op.signatures()[-1]
153         %>
154         if (op[0]->type->base_type == ${first_sig_src_types[0].glsl_type} &&
155             op[1]->type->base_type == ${first_sig_src_types[1].glsl_type}) {
156            data.${first_sig_dst_type.union_field}[c] = ${op.get_c_expression(first_sig_src_types, ("c0", "c1", "c2"))};
157    % for dst_type, src_types in op.signatures()[1:-1]:
158         } else if (op[0]->type->base_type == ${src_types[0].glsl_type} &&
159                    op[1]->type->base_type == ${src_types[1].glsl_type}) {
160            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
161    % endfor
162         } else if (op[0]->type->base_type == ${last_sig_src_types[0].glsl_type} &&
163                    op[1]->type->base_type == ${last_sig_src_types[1].glsl_type}) {
164            data.${last_sig_dst_type.union_field}[c] = ${op.get_c_expression(last_sig_src_types, ("c0", "c1", "c2"))};
165         } else {
166            unreachable("invalid types");
167         }
168      }
169      break;""")
170
171# This template is for multiplication.  It is unique because it has to support
172# matrix * vector and matrix * matrix operations, and those are just different.
173constant_template_mul = mako.template.Template("""\
174   case ${op.get_enum_name()}:
175      /* Check for equal types, or unequal types involving scalars */
176      if ((op[0]->type == op[1]->type && !glsl_type_is_matrix(op[0]->type))
177          || op0_scalar || op1_scalar) {
178         for (unsigned c = 0, c0 = 0, c1 = 0;
179              c < components;
180              c0 += c0_inc, c1 += c1_inc, c++) {
181
182            switch (op[0]->type->base_type) {
183    % for dst_type, src_types in op.signatures():
184            case ${src_types[0].glsl_type}:
185               data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
186               break;
187    % endfor
188            default:
189               unreachable("invalid type");
190            }
191         }
192      } else {
193         assert(glsl_type_is_matrix(op[0]->type) || glsl_type_is_matrix(op[1]->type));
194
195         /* Multiply an N-by-M matrix with an M-by-P matrix.  Since either
196          * matrix can be a GLSL vector, either N or P can be 1.
197          *
198          * For vec*mat, the vector is treated as a row vector.  This
199          * means the vector is a 1-row x M-column matrix.
200          *
201          * For mat*vec, the vector is treated as a column vector.  Since
202          * matrix_columns is 1 for vectors, this just works.
203          */
204         const unsigned n = glsl_type_is_vector(op[0]->type)
205            ? 1 : op[0]->type->vector_elements;
206         const unsigned m = op[1]->type->vector_elements;
207         const unsigned p = op[1]->type->matrix_columns;
208         for (unsigned j = 0; j < p; j++) {
209            for (unsigned i = 0; i < n; i++) {
210               for (unsigned k = 0; k < m; k++) {
211                  if (glsl_type_is_double(op[0]->type))
212                     data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
213                  else
214                     data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
215               }
216            }
217         }
218      }
219      break;""")
220
221# This template is for operations that are horizontal and either have only a
222# single type or the implementation for all types is identical.  That is, the
223# operation consumes a vector and produces a scalar.
224constant_template_horizontal_single_implementation = mako.template.Template("""\
225   case ${op.get_enum_name()}:
226      data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
227      break;""")
228
229# This template is for operations that are horizontal and do not assign the
230# result.  The various unpack operations are examples.
231constant_template_horizontal_nonassignment = mako.template.Template("""\
232   case ${op.get_enum_name()}:
233      ${op.c_expression['default']};
234      break;""")
235
236# This template is for binary operations that are horizontal.  That is, the
237# operation consumes a vector and produces a scalar.
238constant_template_horizontal = mako.template.Template("""\
239   case ${op.get_enum_name()}:
240      switch (op[0]->type->base_type) {
241    % for dst_type, src_types in op.signatures():
242      case ${src_types[0].glsl_type}:
243         data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
244         break;
245    % endfor
246      default:
247         unreachable("invalid type");
248      }
249      break;""")
250
251# This template is for ir_binop_vector_extract.
252constant_template_vector_extract = mako.template.Template("""\
253   case ${op.get_enum_name()}: {
254      const int c = CLAMP(op[1]->value.i[0], 0,
255                          (int) op[0]->type->vector_elements - 1);
256
257      switch (op[0]->type->base_type) {
258    % for dst_type, src_types in op.signatures():
259      case ${src_types[0].glsl_type}:
260         data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
261         break;
262    % endfor
263      default:
264         unreachable("invalid type");
265      }
266      break;
267   }""")
268
269# This template is for ir_triop_vector_insert.
270constant_template_vector_insert = mako.template.Template("""\
271   case ${op.get_enum_name()}: {
272      const unsigned idx = op[2]->value.u[0];
273
274      memcpy(&data, &op[0]->value, sizeof(data));
275
276      switch (return_type->base_type) {
277    % for dst_type, src_types in op.signatures():
278      case ${src_types[0].glsl_type}:
279         data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
280         break;
281    % endfor
282      default:
283         unreachable("invalid type");
284      }
285      break;
286   }""")
287
288# This template is for ir_quadop_vector.
289constant_template_vector = mako.template.Template("""\
290   case ${op.get_enum_name()}:
291      for (unsigned c = 0; c < return_type->vector_elements; c++) {
292         switch (return_type->base_type) {
293    % for dst_type, src_types in op.signatures():
294         case ${src_types[0].glsl_type}:
295            data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
296            break;
297    % endfor
298         default:
299            unreachable("invalid type");
300         }
301      }
302      break;""")
303
304# This template is for ir_triop_lrp.
305constant_template_lrp = mako.template.Template("""\
306   case ${op.get_enum_name()}: {
307      assert(glsl_type_is_float(op[0]->type) || glsl_type_is_double(op[0]->type));
308      assert(glsl_type_is_float(op[1]->type) || glsl_type_is_double(op[1]->type));
309      assert(glsl_type_is_float(op[2]->type) || glsl_type_is_double(op[2]->type));
310
311      unsigned c2_inc = glsl_type_is_scalar(op[2]->type) ? 0 : 1;
312      for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
313         switch (return_type->base_type) {
314    % for dst_type, src_types in op.signatures():
315         case ${src_types[0].glsl_type}:
316            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
317            break;
318    % endfor
319         default:
320            unreachable("invalid type");
321         }
322      }
323      break;
324   }""")
325
326# This template is for ir_triop_csel.  This expression is really unique
327# because not all of the operands are the same type, and the second operand
328# determines the type of the expression (instead of the first).
329constant_template_csel = mako.template.Template("""\
330   case ${op.get_enum_name()}:
331      for (unsigned c = 0; c < components; c++) {
332         switch (return_type->base_type) {
333    % for dst_type, src_types in op.signatures():
334         case ${src_types[1].glsl_type}:
335            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
336            break;
337    % endfor
338         default:
339            unreachable("invalid type");
340         }
341      }
342      break;""")
343
344
345vector_scalar_operation = "vector-scalar"
346horizontal_operation = "horizontal"
347types_identical_operation = "identical"
348non_assign_operation = "nonassign"
349mixed_type_operation = "mixed"
350
351class operation(object):
352   def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None, all_signatures = None):
353      self.name = name
354      self.num_operands = num_operands
355
356      if printable_name is None:
357         self.printable_name = name
358      else:
359         self.printable_name = printable_name
360
361      self.all_signatures = all_signatures
362
363      if source_types is None:
364         self.source_types = tuple()
365      else:
366         self.source_types = source_types
367
368      self.dest_type = dest_type
369
370      if c_expression is None:
371         self.c_expression = None
372      elif isinstance(c_expression, str):
373         self.c_expression = {'default': c_expression}
374      else:
375         self.c_expression = c_expression
376
377      if flags is None:
378         self.flags = frozenset()
379      elif isinstance(flags, str):
380         self.flags = frozenset([flags])
381      else:
382         self.flags = frozenset(flags)
383
384
385   def get_enum_name(self):
386      return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name)
387
388
389   def get_template(self):
390      if self.c_expression is None:
391         return None
392
393      if horizontal_operation in self.flags:
394         if non_assign_operation in self.flags:
395            return constant_template_horizontal_nonassignment.render(op=self)
396         elif types_identical_operation in self.flags:
397            return constant_template_horizontal_single_implementation.render(op=self)
398         else:
399            return constant_template_horizontal.render(op=self)
400
401      if self.num_operands == 2:
402         if self.name == "mul":
403            return constant_template_mul.render(op=self)
404         elif self.name == "vector_extract":
405            return constant_template_vector_extract.render(op=self)
406         elif vector_scalar_operation in self.flags:
407            if mixed_type_operation in self.flags:
408               return constant_template_vector_scalar_mixed.render(op=self)
409            else:
410               return constant_template_vector_scalar.render(op=self)
411      elif self.num_operands == 3:
412         if self.name == "vector_insert":
413            return constant_template_vector_insert.render(op=self)
414         elif self.name == "lrp":
415            return constant_template_lrp.render(op=self)
416         elif self.name == "csel":
417            return constant_template_csel.render(op=self)
418      elif self.num_operands == 4:
419         if self.name == "vector":
420            return constant_template_vector.render(op=self)
421
422      return constant_template_common.render(op=self)
423
424
425   def get_c_expression(self, types, indices=("c", "c", "c")):
426      src0 = "op[0]->value.{0}[{1}]".format(types[0].union_field, indices[0])
427      src1 = "op[1]->value.{0}[{1}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
428      src2 = "op[2]->value.{0}[{1}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR"
429      src3 = "op[3]->value.{0}[c]".format(types[3].union_field) if len(types) >= 4 else "ERROR"
430
431      expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default']
432
433      return expr.format(src0=src0,
434                         src1=src1,
435                         src2=src2,
436                         src3=src3)
437
438
439   def signatures(self):
440      if self.all_signatures is not None:
441         return self.all_signatures
442      else:
443         return type_signature_iter(self.dest_type, self.source_types, self.num_operands)
444
445
446ir_expression_operation = [
447   operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
448   operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
449   operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'u64': "-((int64_t) {src0})", 'default': "-{src0}"}),
450   operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})", 'i64': "{src0} < 0 ? -{src0} : {src0}"}),
451   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))", 'i64': "({src0} > 0) - ({src0} < 0)"}),
452   operation("rcp", 1, source_types=real_types, c_expression={'f': "1.0F / {src0}", 'd': "1.0 / {src0}"}),
453   operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
454   operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
455   operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"),         # Log base e on gentype
456   operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"),         # Natural log on gentype
457   operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"),
458   operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"),
459
460   # Float-to-integer conversion.
461   operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"),
462   # Float-to-unsigned conversion.
463   operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"),
464   # Integer-to-float conversion.
465   operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"),
466   # Float-to-boolean conversion
467   operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"),
468   # Boolean-to-float conversion
469   operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
470   # Boolean-to-float16 conversion
471   operation("b2f16", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
472   # int-to-boolean conversion
473   operation("i2b", 1, source_types=(uint_type, int_type), dest_type=bool_type, c_expression="{src0} ? true : false"),
474   # Boolean-to-int conversion
475   operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
476   # Unsigned-to-float conversion.
477   operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
478   # Integer-to-unsigned conversion.
479   operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
480   # Unsigned-to-integer conversion.
481   operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
482   # Double-to-float conversion.
483   operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
484   # Float-to-double conversion.
485   operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
486   # Half-float conversions. These all operate on and return float types,
487   # since the framework expands half to full float before calling in.  We
488   # still have to handle them here so that we can constant propagate through
489   # them, but they are no-ops.
490   operation("f2f16", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
491   operation("f2fmp", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
492   operation("f162f", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
493   operation("u2f16", 1, source_types=(uint_type,), dest_type=float_type, c_expression="{src0}"),
494   operation("f162u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="{src0}"),
495   operation("i2f16", 1, source_types=(int_type,), dest_type=float_type, c_expression="{src0}"),
496   operation("f162i", 1, source_types=(float_type,), dest_type=int_type, c_expression="{src0}"),
497   operation("d2f16", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
498   operation("f162d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
499   operation("u642f16", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"),
500   operation("f162u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"),
501   operation("i642f16", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"),
502   operation("f162i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"),
503   # int16<->int32 conversion.
504   operation("i2i", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"),
505   operation("i2imp", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"),
506   operation("u2u", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"),
507   operation("u2ump", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"),
508   # Double-to-integer conversion.
509   operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
510   # Integer-to-double conversion.
511   operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
512   # Double-to-unsigned conversion.
513   operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
514   # Unsigned-to-double conversion.
515   operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
516   # Double-to-boolean conversion.
517   operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
518   # Float16-to-boolean conversion.
519   operation("f162b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
520   # 'Bit-identical int-to-float "conversion"
521   operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
522   # 'Bit-identical float-to-int "conversion"
523   operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
524   # 'Bit-identical uint-to-float "conversion"
525   operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
526   # 'Bit-identical float-to-uint "conversion"
527   operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
528   # Bit-identical u64-to-double "conversion"
529   operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="bitcast_u642d({src0})"),
530   # Bit-identical i64-to-double "conversion"
531   operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="bitcast_i642d({src0})"),
532   # Bit-identical double-to_u64 "conversion"
533   operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="bitcast_d2u64({src0})"),
534   # Bit-identical double-to-i64 "conversion"
535   operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="bitcast_d2i64({src0})"),
536   # i64-to-i32 conversion
537   operation("i642i", 1, source_types=(int64_type,), dest_type=int_type, c_expression="{src0}"),
538   # ui64-to-i32 conversion
539   operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type, c_expression="{src0}"),
540   operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type, c_expression="{src0}"),
541   operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type, c_expression="{src0}"),
542   operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type, c_expression="{src0} != 0"),
543   operation("i642f", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"),
544   operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"),
545   operation("i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="{src0}"),
546   operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="{src0}"),
547   operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type, c_expression="{src0}"),
548   operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type, c_expression="{src0}"),
549   operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type, c_expression="{src0}"),
550   operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"),
551   operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="{src0}"),
552   operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type, c_expression="{src0}"),
553   operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type, c_expression="{src0}"),
554   operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"),
555   operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="{src0}"),
556   operation("u642i64", 1, source_types=(uint64_type,), dest_type=int64_type, c_expression="{src0}"),
557   operation("i642u64", 1, source_types=(int64_type,), dest_type=uint64_type, c_expression="{src0}"),
558
559
560   # Unary floating-point rounding operations.
561   operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
562   operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
563   operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
564   operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
565   operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
566
567   # Trigonometric operations.
568   operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
569   operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
570   operation("atan", 1, source_types=(float_type,), c_expression="atan({src0})"),
571
572   # Partial derivatives.
573   operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
574   operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
575   operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
576   operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
577   operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
578   operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
579
580   # Floating point pack and unpack operations.
581   operation("pack_snorm_2x16", 1, printable_name="packSnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_snorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
582   operation("pack_snorm_4x8", 1, printable_name="packSnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_snorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation),
583   operation("pack_unorm_2x16", 1, printable_name="packUnorm2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_unorm_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
584   operation("pack_unorm_4x8", 1, printable_name="packUnorm4x8", source_types=(float_type,), dest_type=uint_type, c_expression="pack_4x8(pack_unorm_1x8, op[0]->value.f[0], op[0]->value.f[1], op[0]->value.f[2], op[0]->value.f[3])", flags=horizontal_operation),
585   operation("pack_half_2x16", 1, printable_name="packHalf2x16", source_types=(float_type,), dest_type=uint_type, c_expression="pack_2x16(pack_half_1x16, op[0]->value.f[0], op[0]->value.f[1])", flags=horizontal_operation),
586   operation("unpack_snorm_2x16", 1, printable_name="unpackSnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_snorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
587   operation("unpack_snorm_4x8", 1, printable_name="unpackSnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_snorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))),
588   operation("unpack_unorm_2x16", 1, printable_name="unpackUnorm2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_unorm_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
589   operation("unpack_unorm_4x8", 1, printable_name="unpackUnorm4x8", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_4x8(unpack_unorm_1x8, op[0]->value.u[0], &data.f[0], &data.f[1], &data.f[2], &data.f[3])", flags=frozenset((horizontal_operation, non_assign_operation))),
590   operation("unpack_half_2x16", 1, printable_name="unpackHalf2x16", source_types=(uint_type,), dest_type=float_type, c_expression="unpack_2x16(unpack_half_1x16, op[0]->value.u[0], &data.f[0], &data.f[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
591
592   # Bit operations, part of ARB_gpu_shader5.
593   operation("bitfield_reverse", 1, source_types=(uint_type, int_type), c_expression="bitfield_reverse({src0})"),
594   operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="util_bitcount({src0})"),
595   operation("find_msb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
596   operation("find_lsb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
597   operation("clz", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="(unsigned)(31 - find_msb_uint({src0}))"),
598
599   operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
600
601   # Double packing, part of ARB_gpu_shader_fp64.
602   operation("pack_double_2x32", 1, printable_name="packDouble2x32", source_types=(uint_type,), dest_type=double_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
603   operation("unpack_double_2x32", 1, printable_name="unpackDouble2x32", source_types=(double_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
604
605   # Sampler/Image packing, part of ARB_bindless_texture.
606   operation("pack_sampler_2x32", 1, printable_name="packSampler2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
607   operation("pack_image_2x32", 1, printable_name="packImage2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
608   operation("unpack_sampler_2x32", 1, printable_name="unpackSampler2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
609   operation("unpack_image_2x32", 1, printable_name="unpackImage2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
610
611   operation("frexp_sig", 1),
612   operation("frexp_exp", 1),
613
614   operation("subroutine_to_int", 1),
615
616   # Interpolate fs input at centroid
617   #
618   # operand0 is the fs input.
619   operation("interpolate_at_centroid", 1),
620
621   # Ask the driver for the total size of a buffer block.
622   # operand0 is the ir_constant buffer block index in the linked shader.
623   operation("get_buffer_size", 1),
624
625   # Calculate length of an unsized array inside a buffer block.
626   # This opcode is going to be replaced in a lowering pass inside
627   # the linker.
628   #
629   # operand0 is the unsized array's ir_value for the calculation
630   # of its length.
631   operation("ssbo_unsized_array_length", 1),
632
633   # Calculate length of an implicitly sized array.
634   # This opcode is going to be replaced with a constant expression at link
635   # time.
636   operation("implicitly_sized_array_length", 1),
637
638   # 64-bit integer packing ops.
639   operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
640   operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
641   operation("unpack_int_2x32", 1, printable_name="unpackInt2x32", source_types=(int64_type,), dest_type=int_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
642   operation("unpack_uint_2x32", 1, printable_name="unpackUint2x32", source_types=(uint64_type,), dest_type=uint_type, c_expression="unpack_2x32(op[0]->value.u64[0], &data.u[0], &data.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
643
644   operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
645   operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
646   operation("add_sat", 2, printable_name="add_sat", source_types=integer_types, c_expression={
647      'u': "({src0} + {src1}) < {src0} ? UINT32_MAX : ({src0} + {src1})",
648      'i': "iadd_saturate({src0}, {src1})",
649      'u64': "({src0} + {src1}) < {src0} ? UINT64_MAX : ({src0} + {src1})",
650      'i64': "iadd64_saturate({src0}, {src1})"
651   }),
652   operation("sub_sat", 2, printable_name="sub_sat", source_types=integer_types, c_expression={
653      'u': "({src1} > {src0}) ? 0 : {src0} - {src1}",
654      'i': "isub_saturate({src0}, {src1})",
655      'u64': "({src1} > {src0}) ? 0 : {src0} - {src1}",
656      'i64': "isub64_saturate({src0}, {src1})"
657   }),
658   operation("abs_sub", 2, printable_name="abs_sub", source_types=integer_types, c_expression={
659      'u': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
660      'i': "({src1} > {src0}) ? (unsigned){src1} - (unsigned){src0} : (unsigned){src0} - (unsigned){src1}",
661      'u64': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
662      'i64': "({src1} > {src0}) ? (uint64_t){src1} - (uint64_t){src0} : (uint64_t){src0} - (uint64_t){src1}",
663   }),
664   operation("avg", 2, printable_name="average", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} & {src1}) & 1)"),
665   operation("avg_round", 2, printable_name="average_rounded", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} | {src1}) & 1)"),
666
667   # "Floating-point or low 32-bit integer multiply."
668   operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
669   operation("mul_32x16", 2, printable_name="*", source_types=(uint_type, int_type), c_expression={
670      'u': "{src0} * (uint16_t){src1}",
671      'i': "{src0} * (int16_t){src0}"
672   }),
673   operation("imul_high", 2),       # Calculates the high 32-bits of a 64-bit multiply.
674   operation("div", 2, printable_name="/", source_types=numeric_types, c_expression={'u': "{src1} == 0 ? 0 : {src0} / {src1}", 'i': "{src1} == 0 ? 0 : {src0} / {src1}", 'u64': "{src1} == 0 ? 0 : {src0} / {src1}", 'i64': "{src1} == 0 ? 0 : {src0} / {src1}", 'default': "{src0} / {src1}"}, flags=vector_scalar_operation),
675
676   # Returns the carry resulting from the addition of the two arguments.
677   operation("carry", 2),
678
679   # Returns the borrow resulting from the subtraction of the second argument
680   # from the first argument.
681   operation("borrow", 2),
682
683   # Either (vector % vector) or (vector % scalar)
684   #
685   # We don't use fmod because it rounds toward zero; GLSL specifies the use
686   # of floor.
687   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})", 'u64': "{src1} == 0 ? 0 : {src0} % {src1}", 'i64': "{src1} == 0 ? 0 : {src0} % {src1}"}, flags=vector_scalar_operation),
688
689   # Binary comparison operators which return a boolean vector.
690   # The type of both operands must be equal.
691   operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"),
692   operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"),
693   operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"),
694   operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"),
695
696   # Returns single boolean for whether all components of operands[0]
697   # equal the components of operands[1].
698   operation("all_equal", 2, source_types=all_types, dest_type=bool_type, c_expression="op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))),
699
700   # Returns single boolean for whether any component of operands[0]
701   # is not equal to the corresponding component of operands[1].
702   operation("any_nequal", 2, source_types=all_types, dest_type=bool_type, c_expression="!op[0]->has_value(op[1])", flags=frozenset((horizontal_operation, types_identical_operation))),
703
704   # Bit-wise binary operations.
705   operation("lshift", 2,
706             printable_name="<<", all_signatures=list((src_sig[0], src_sig) for src_sig in itertools.product(integer_types, repeat=2)),
707             source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
708   operation("rshift", 2,
709             printable_name=">>", all_signatures=list((src_sig[0], src_sig) for src_sig in itertools.product(integer_types, repeat=2)),
710             source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
711   operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
712   operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
713   operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
714
715   operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
716   operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
717   operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
718
719   operation("dot", 2, source_types=real_types, c_expression={'f': "dot_f(op[0], op[1])", 'd': "dot_d(op[0], op[1])"}, flags=horizontal_operation),
720   operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
721   operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
722
723   operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
724
725   # Multiplies a number by two to a power, part of ARB_gpu_shader5.
726   operation("ldexp", 2,
727             all_signatures=((float_type, (float_type, int_type)),
728                             (double_type, (double_type, int_type))),
729             c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})",
730                           'd': "ldexp_flush_subnormal({src0}, {src1})"}),
731
732   # Extract a scalar from a vector
733   #
734   # operand0 is the vector
735   # operand1 is the index of the field to read from operand0
736   operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"),
737
738   # Interpolate fs input at offset
739   #
740   # operand0 is the fs input
741   # operand1 is the offset from the pixel center
742   operation("interpolate_at_offset", 2),
743
744   # Interpolate fs input at sample position
745   #
746   # operand0 is the fs input
747   # operand1 is the sample ID
748   operation("interpolate_at_sample", 2),
749
750   operation("atan2", 2, source_types=(float_type,), c_expression="atan2({src0}, {src1})"),
751
752   # Fused floating-point multiply-add, part of ARB_gpu_shader5.
753   operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"),
754
755   operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
756
757   # Conditional Select
758   #
759   # A vector conditional select instruction (like ?:, but operating per-
760   # component on vectors).
761   #
762   # See also lower_instructions_visitor::ldexp_to_arith
763   operation("csel", 3,
764             all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)),
765             c_expression="{src0} ? {src1} : {src2}"),
766
767   operation("bitfield_extract", 3,
768             all_signatures=((int_type, (uint_type, int_type, int_type)),
769                             (int_type, (int_type, int_type, int_type))),
770             c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
771                           'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
772
773   # Generate a value with one field of a vector changed
774   #
775   # operand0 is the vector
776   # operand1 is the value to write into the vector result
777   # operand2 is the index in operand0 to be modified
778   operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"),
779
780   operation("bitfield_insert", 4,
781             all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)),
782                             (int_type, (int_type, int_type, int_type, int_type))),
783             c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
784
785   operation("vector", 4, source_types=all_types, c_expression="anything-except-None"),
786]
787
788
789if __name__ == "__main__":
790   copyright = """/*
791 * Copyright (C) 2010 Intel Corporation
792 *
793 * Permission is hereby granted, free of charge, to any person obtaining a
794 * copy of this software and associated documentation files (the "Software"),
795 * to deal in the Software without restriction, including without limitation
796 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
797 * and/or sell copies of the Software, and to permit persons to whom the
798 * Software is furnished to do so, subject to the following conditions:
799 *
800 * The above copyright notice and this permission notice (including the next
801 * paragraph) shall be included in all copies or substantial portions of the
802 * Software.
803 *
804 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
805 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
806 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
807 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
808 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
809 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
810 * DEALINGS IN THE SOFTWARE.
811 */
812"""
813   enum_template = mako.template.Template(copyright + """
814enum ir_expression_operation {
815% for item in values:
816   ${item.get_enum_name()},
817% endfor
818
819   /* Sentinels marking the last of each kind of operation. */
820% for item in lasts:
821   ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
822% endfor
823   ir_last_opcode = ir_quadop_${lasts[3].name}
824};""")
825
826   strings_template = mako.template.Template(copyright + """
827const char *const ir_expression_operation_strings[] = {
828% for item in values:
829   "${item.printable_name}",
830% endfor
831};
832
833const char *const ir_expression_operation_enum_strings[] = {
834% for item in values:
835   "${item.name}",
836% endfor
837};""")
838
839   constant_template = mako.template.Template("""\
840   switch (this->operation) {
841% for op in values:
842    % if op.c_expression is not None:
843${op.get_template()}
844
845    % endif
846% endfor
847   default:
848      /* FINISHME: Should handle all expression types. */
849      return NULL;
850   }
851""")
852
853   if sys.argv[1] == "enum":
854      lasts = [None, None, None, None]
855      for item in reversed(ir_expression_operation):
856         i = item.num_operands - 1
857         if lasts[i] is None:
858            lasts[i] = item
859
860      print(enum_template.render(values=ir_expression_operation,
861                                 lasts=lasts))
862   elif sys.argv[1] == "strings":
863      print(strings_template.render(values=ir_expression_operation))
864   elif sys.argv[1] == "constant":
865      print(constant_template.render(values=ir_expression_operation))
866