• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
24import mako.template
25import sys
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
81uint_type = type("unsigned", "u", "GLSL_TYPE_UINT")
82int_type = type("int", "i", "GLSL_TYPE_INT")
83float_type = type("float", "f", "GLSL_TYPE_FLOAT")
84double_type = type("double", "d", "GLSL_TYPE_DOUBLE")
85bool_type = type("bool", "b", "GLSL_TYPE_BOOL")
86
87all_types = (uint_type, int_type, float_type, double_type, bool_type)
88numeric_types = (uint_type, int_type, float_type, double_type)
89signed_numeric_types = (int_type, float_type, double_type)
90integer_types = (uint_type, int_type)
91real_types = (float_type, double_type)
92
93# This template is for operations that can have operands of a several
94# different types, and each type may or may not has a different C expression.
95# This is used by most operations.
96constant_template_common = mako.template.Template("""\
97   case ${op.get_enum_name()}:
98      for (unsigned c = 0; c < op[0]->type->components(); c++) {
99         switch (op[0]->type->base_type) {
100    % for dst_type, src_types in op.signatures():
101         case ${src_types[0].glsl_type}:
102            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
103            break;
104    % endfor
105         default:
106            unreachable("invalid type");
107         }
108      }
109      break;""")
110
111# This template is for binary operations that can operate on some combination
112# of scalar and vector operands.
113constant_template_vector_scalar = mako.template.Template("""\
114   case ${op.get_enum_name()}:
115    % if "mixed" in op.flags:
116        % for i in xrange(op.num_operands):
117      assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
118            % for src_type in op.source_types[1:-1]:
119             op[${i}]->type->base_type == ${src_type.glsl_type} ||
120            % endfor
121             op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
122        % endfor
123    % else:
124      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
125    % endif
126      for (unsigned c = 0, c0 = 0, c1 = 0;
127           c < components;
128           c0 += c0_inc, c1 += c1_inc, c++) {
129
130         switch (op[0]->type->base_type) {
131    % for dst_type, src_types in op.signatures():
132         case ${src_types[0].glsl_type}:
133            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
134            break;
135    % endfor
136         default:
137            unreachable("invalid type");
138         }
139      }
140      break;""")
141
142# This template is for multiplication.  It is unique because it has to support
143# matrix * vector and matrix * matrix operations, and those are just different.
144constant_template_mul = mako.template.Template("""\
145   case ${op.get_enum_name()}:
146      /* Check for equal types, or unequal types involving scalars */
147      if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
148          || 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", "c2"))};
157               break;
158    % endfor
159            default:
160               unreachable("invalid type");
161            }
162         }
163      } else {
164         assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
165
166         /* Multiply an N-by-M matrix with an M-by-P matrix.  Since either
167          * matrix can be a GLSL vector, either N or P can be 1.
168          *
169          * For vec*mat, the vector is treated as a row vector.  This
170          * means the vector is a 1-row x M-column matrix.
171          *
172          * For mat*vec, the vector is treated as a column vector.  Since
173          * matrix_columns is 1 for vectors, this just works.
174          */
175         const unsigned n = op[0]->type->is_vector()
176            ? 1 : op[0]->type->vector_elements;
177         const unsigned m = op[1]->type->vector_elements;
178         const unsigned p = op[1]->type->matrix_columns;
179         for (unsigned j = 0; j < p; j++) {
180            for (unsigned i = 0; i < n; i++) {
181               for (unsigned k = 0; k < m; k++) {
182                  if (op[0]->type->base_type == GLSL_TYPE_DOUBLE)
183                     data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
184                  else
185                     data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
186               }
187            }
188         }
189      }
190      break;""")
191
192# This template is for operations that are horizontal and either have only a
193# single type or the implementation for all types is identical.  That is, the
194# operation consumes a vector and produces a scalar.
195constant_template_horizontal_single_implementation = mako.template.Template("""\
196   case ${op.get_enum_name()}:
197      data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
198      break;""")
199
200# This template is for operations that are horizontal and do not assign the
201# result.  The various unpack operations are examples.
202constant_template_horizontal_nonassignment = mako.template.Template("""\
203   case ${op.get_enum_name()}:
204      ${op.c_expression['default']};
205      break;""")
206
207# This template is for binary operations that are horizontal.  That is, the
208# operation consumes a vector and produces a scalar.
209constant_template_horizontal = mako.template.Template("""\
210   case ${op.get_enum_name()}:
211      switch (op[0]->type->base_type) {
212    % for dst_type, src_types in op.signatures():
213      case ${src_types[0].glsl_type}:
214         data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
215         break;
216    % endfor
217      default:
218         unreachable("invalid type");
219      }
220      break;""")
221
222# This template is for ir_binop_vector_extract.
223constant_template_vector_extract = mako.template.Template("""\
224   case ${op.get_enum_name()}: {
225      const int c = CLAMP(op[1]->value.i[0], 0,
226                          (int) op[0]->type->vector_elements - 1);
227
228      switch (op[0]->type->base_type) {
229    % for dst_type, src_types in op.signatures():
230      case ${src_types[0].glsl_type}:
231         data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
232         break;
233    % endfor
234      default:
235         unreachable("invalid type");
236      }
237      break;
238   }""")
239
240# This template is for ir_triop_vector_insert.
241constant_template_vector_insert = mako.template.Template("""\
242   case ${op.get_enum_name()}: {
243      const unsigned idx = op[2]->value.u[0];
244
245      memcpy(&data, &op[0]->value, sizeof(data));
246
247      switch (this->type->base_type) {
248    % for dst_type, src_types in op.signatures():
249      case ${src_types[0].glsl_type}:
250         data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
251         break;
252    % endfor
253      default:
254         unreachable("invalid type");
255      }
256      break;
257   }""")
258
259# This template is for ir_quadop_vector.
260constant_template_vector = mako.template.Template("""\
261   case ${op.get_enum_name()}:
262      for (unsigned c = 0; c < this->type->vector_elements; c++) {
263         switch (this->type->base_type) {
264    % for dst_type, src_types in op.signatures():
265         case ${src_types[0].glsl_type}:
266            data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
267            break;
268    % endfor
269         default:
270            unreachable("invalid type");
271         }
272      }
273      break;""")
274
275# This template is for ir_triop_lrp.
276constant_template_lrp = mako.template.Template("""\
277   case ${op.get_enum_name()}: {
278      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT ||
279             op[0]->type->base_type == GLSL_TYPE_DOUBLE);
280      assert(op[1]->type->base_type == GLSL_TYPE_FLOAT ||
281             op[1]->type->base_type == GLSL_TYPE_DOUBLE);
282      assert(op[2]->type->base_type == GLSL_TYPE_FLOAT ||
283             op[2]->type->base_type == GLSL_TYPE_DOUBLE);
284
285      unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
286      for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
287         switch (this->type->base_type) {
288    % for dst_type, src_types in op.signatures():
289         case ${src_types[0].glsl_type}:
290            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
291            break;
292    % endfor
293         default:
294            unreachable("invalid type");
295         }
296      }
297      break;
298   }""")
299
300# This template is for ir_triop_csel.  This expression is really unique
301# because not all of the operands are the same type, and the second operand
302# determines the type of the expression (instead of the first).
303constant_template_csel = mako.template.Template("""\
304   case ${op.get_enum_name()}:
305      for (unsigned c = 0; c < components; c++) {
306         switch (this->type->base_type) {
307    % for dst_type, src_types in op.signatures():
308         case ${src_types[1].glsl_type}:
309            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
310            break;
311    % endfor
312         default:
313            unreachable("invalid type");
314         }
315      }
316      break;""")
317
318
319vector_scalar_operation = "vector-scalar"
320horizontal_operation = "horizontal"
321types_identical_operation = "identical"
322non_assign_operation = "nonassign"
323mixed_type_operation = "mixed"
324
325class operation(object):
326   def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None, all_signatures = None):
327      self.name = name
328      self.num_operands = num_operands
329
330      if printable_name is None:
331         self.printable_name = name
332      else:
333         self.printable_name = printable_name
334
335      self.all_signatures = all_signatures
336
337      if source_types is None:
338         self.source_types = tuple()
339      else:
340         self.source_types = source_types
341
342      self.dest_type = dest_type
343
344      if c_expression is None:
345         self.c_expression = None
346      elif isinstance(c_expression, str):
347         self.c_expression = {'default': c_expression}
348      else:
349         self.c_expression = c_expression
350
351      if flags is None:
352         self.flags = frozenset()
353      elif isinstance(flags, str):
354         self.flags = frozenset([flags])
355      else:
356         self.flags = frozenset(flags)
357
358
359   def get_enum_name(self):
360      return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name)
361
362
363   def get_template(self):
364      if self.c_expression is None:
365         return None
366
367      if horizontal_operation in self.flags:
368         if non_assign_operation in self.flags:
369            return constant_template_horizontal_nonassignment.render(op=self)
370         elif types_identical_operation in self.flags:
371            return constant_template_horizontal_single_implementation.render(op=self)
372         else:
373            return constant_template_horizontal.render(op=self)
374
375      if self.num_operands == 2:
376         if self.name == "mul":
377            return constant_template_mul.render(op=self)
378         elif self.name == "vector_extract":
379            return constant_template_vector_extract.render(op=self)
380         elif vector_scalar_operation in self.flags:
381            return constant_template_vector_scalar.render(op=self)
382      elif self.num_operands == 3:
383         if self.name == "vector_insert":
384            return constant_template_vector_insert.render(op=self)
385         elif self.name == "lrp":
386            return constant_template_lrp.render(op=self)
387         elif self.name == "csel":
388            return constant_template_csel.render(op=self)
389      elif self.num_operands == 4:
390         if self.name == "vector":
391            return constant_template_vector.render(op=self)
392
393      return constant_template_common.render(op=self)
394
395
396   def get_c_expression(self, types, indices=("c", "c", "c")):
397      src0 = "op[0]->value.{0}[{1}]".format(types[0].union_field, indices[0])
398      src1 = "op[1]->value.{0}[{1}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
399      src2 = "op[2]->value.{0}[{1}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR"
400      src3 = "op[3]->value.{0}[c]".format(types[3].union_field) if len(types) >= 4 else "ERROR"
401
402      expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default']
403
404      return expr.format(src0=src0,
405                         src1=src1,
406                         src2=src2,
407                         src3=src3)
408
409
410   def signatures(self):
411      if self.all_signatures is not None:
412         return self.all_signatures
413      else:
414         return type_signature_iter(self.dest_type, self.source_types, self.num_operands)
415
416
417ir_expression_operation = [
418   operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
419   operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
420   operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'default': "-{src0}"}),
421   operation("abs", 1, source_types=signed_numeric_types, c_expression={'i': "{src0} < 0 ? -{src0} : {src0}", 'f': "fabsf({src0})", 'd': "fabs({src0})"}),
422   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))"}),
423   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"}),
424   operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
425   operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
426   operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"),         # Log base e on gentype
427   operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"),         # Natural log on gentype
428   operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"),
429   operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"),
430
431   # Float-to-integer conversion.
432   operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"),
433   # Float-to-unsigned conversion.
434   operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"),
435   # Integer-to-float conversion.
436   operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"),
437   # Float-to-boolean conversion
438   operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"),
439   # Boolean-to-float conversion
440   operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
441   # int-to-boolean conversion
442   operation("i2b", 1, source_types=integer_types, dest_type=bool_type, c_expression="{src0} ? true : false"),
443   # Boolean-to-int conversion
444   operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
445   # Unsigned-to-float conversion.
446   operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
447   # Integer-to-unsigned conversion.
448   operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
449   # Unsigned-to-integer conversion.
450   operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
451   # Double-to-float conversion.
452   operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
453   # Float-to-double conversion.
454   operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
455   # Double-to-integer conversion.
456   operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
457   # Integer-to-double conversion.
458   operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
459   # Double-to-unsigned conversion.
460   operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
461   # Unsigned-to-double conversion.
462   operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
463   # Double-to-boolean conversion.
464   operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
465   # 'Bit-identical int-to-float "conversion"
466   operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
467   # 'Bit-identical float-to-int "conversion"
468   operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
469   # 'Bit-identical uint-to-float "conversion"
470   operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
471   # 'Bit-identical float-to-uint "conversion"
472   operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
473
474   # Unary floating-point rounding operations.
475   operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
476   operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
477   operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
478   operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
479   operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
480
481   # Trigonometric operations.
482   operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
483   operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
484
485   # Partial derivatives.
486   operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
487   operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
488   operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
489   operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
490   operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
491   operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
492
493   # Floating point pack and unpack operations.
494   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),
495   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),
496   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),
497   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),
498   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),
499   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))),
500   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))),
501   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))),
502   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))),
503   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))),
504
505   # Bit operations, part of ARB_gpu_shader5.
506   operation("bitfield_reverse", 1, source_types=integer_types, c_expression="bitfield_reverse({src0})"),
507   operation("bit_count", 1, source_types=integer_types, dest_type=int_type, c_expression="_mesa_bitcount({src0})"),
508   operation("find_msb", 1, source_types=integer_types, dest_type=int_type, c_expression={'u': "find_msb_uint({src0})", 'i': "find_msb_int({src0})"}),
509   operation("find_lsb", 1, source_types=integer_types, dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
510
511   operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
512
513   # Double packing, part of ARB_gpu_shader_fp64.
514   operation("pack_double_2x32", 1, printable_name="packDouble2x32", source_types=(uint_type,), dest_type=double_type, c_expression="memcpy(&data.d[0], &op[0]->value.u[0], sizeof(double))", flags=frozenset((horizontal_operation, non_assign_operation))),
515   operation("unpack_double_2x32", 1, printable_name="unpackDouble2x32", source_types=(double_type,), dest_type=uint_type, c_expression="memcpy(&data.u[0], &op[0]->value.d[0], sizeof(double))", flags=frozenset((horizontal_operation, non_assign_operation))),
516
517   operation("frexp_sig", 1),
518   operation("frexp_exp", 1),
519
520   operation("noise", 1),
521
522   operation("subroutine_to_int", 1),
523
524   # Interpolate fs input at centroid
525   #
526   # operand0 is the fs input.
527   operation("interpolate_at_centroid", 1),
528
529   # Ask the driver for the total size of a buffer block.
530   # operand0 is the ir_constant buffer block index in the linked shader.
531   operation("get_buffer_size", 1),
532
533   # Calculate length of an unsized array inside a buffer block.
534   # This opcode is going to be replaced in a lowering pass inside
535   # the linker.
536   #
537   # operand0 is the unsized array's ir_value for the calculation
538   # of its length.
539   operation("ssbo_unsized_array_length", 1),
540
541   # Vote among threads on the value of the boolean argument.
542   operation("vote_any", 1),
543   operation("vote_all", 1),
544   operation("vote_eq", 1),
545
546   operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
547   operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
548   # "Floating-point or low 32-bit integer multiply."
549   operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
550   operation("imul_high", 2),       # Calculates the high 32-bits of a 64-bit multiply.
551   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),
552
553   # Returns the carry resulting from the addition of the two arguments.
554   operation("carry", 2),
555
556   # Returns the borrow resulting from the subtraction of the second argument
557   # from the first argument.
558   operation("borrow", 2),
559
560   # Either (vector % vector) or (vector % scalar)
561   #
562   # We don't use fmod because it rounds toward zero; GLSL specifies the use
563   # of floor.
564   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),
565
566   # Binary comparison operators which return a boolean vector.
567   # The type of both operands must be equal.
568   operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"),
569   operation("greater", 2, printable_name=">", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} > {src1}"),
570   operation("lequal", 2, printable_name="<=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} <= {src1}"),
571   operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"),
572   operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"),
573   operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"),
574
575   # Returns single boolean for whether all components of operands[0]
576   # equal the components of operands[1].
577   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))),
578
579   # Returns single boolean for whether any component of operands[0]
580   # is not equal to the corresponding component of operands[1].
581   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))),
582
583   # Bit-wise binary operations.
584   operation("lshift", 2, printable_name="<<", source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
585   operation("rshift", 2, printable_name=">>", source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
586   operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
587   operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
588   operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
589
590   operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
591   operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
592   operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
593
594   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),
595   operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
596   operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
597
598   operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
599
600   # Load a value the size of a given GLSL type from a uniform block.
601   #
602   # operand0 is the ir_constant uniform block index in the linked shader.
603   # operand1 is a byte offset within the uniform block.
604   operation("ubo_load", 2),
605
606   # Multiplies a number by two to a power, part of ARB_gpu_shader5.
607   operation("ldexp", 2,
608             all_signatures=((float_type, (float_type, int_type)),
609                             (double_type, (double_type, int_type))),
610             c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})",
611                           'd': "ldexp_flush_subnormal({src0}, {src1})"}),
612
613   # Extract a scalar from a vector
614   #
615   # operand0 is the vector
616   # operand1 is the index of the field to read from operand0
617   operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"),
618
619   # Interpolate fs input at offset
620   #
621   # operand0 is the fs input
622   # operand1 is the offset from the pixel center
623   operation("interpolate_at_offset", 2),
624
625   # Interpolate fs input at sample position
626   #
627   # operand0 is the fs input
628   # operand1 is the sample ID
629   operation("interpolate_at_sample", 2),
630
631   # Fused floating-point multiply-add, part of ARB_gpu_shader5.
632   operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"),
633
634   operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
635
636   # Conditional Select
637   #
638   # A vector conditional select instruction (like ?:, but operating per-
639   # component on vectors).
640   #
641   # See also lower_instructions_visitor::ldexp_to_arith
642   operation("csel", 3,
643             all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)),
644             c_expression="{src0} ? {src1} : {src2}"),
645
646   operation("bitfield_extract", 3,
647             all_signatures=((int_type, (uint_type, int_type, int_type)),
648                             (int_type, (int_type, int_type, int_type))),
649             c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
650                           'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
651
652   # Generate a value with one field of a vector changed
653   #
654   # operand0 is the vector
655   # operand1 is the value to write into the vector result
656   # operand2 is the index in operand0 to be modified
657   operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"),
658
659   operation("bitfield_insert", 4,
660             all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)),
661                             (int_type, (int_type, int_type, int_type, int_type))),
662             c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
663
664   operation("vector", 4, source_types=all_types, c_expression="anything-except-None"),
665]
666
667
668if __name__ == "__main__":
669   copyright = """/*
670 * Copyright (C) 2010 Intel Corporation
671 *
672 * Permission is hereby granted, free of charge, to any person obtaining a
673 * copy of this software and associated documentation files (the "Software"),
674 * to deal in the Software without restriction, including without limitation
675 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
676 * and/or sell copies of the Software, and to permit persons to whom the
677 * Software is furnished to do so, subject to the following conditions:
678 *
679 * The above copyright notice and this permission notice (including the next
680 * paragraph) shall be included in all copies or substantial portions of the
681 * Software.
682 *
683 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
684 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
685 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
686 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
687 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
688 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
689 * DEALINGS IN THE SOFTWARE.
690 */
691"""
692   enum_template = mako.template.Template(copyright + """
693enum ir_expression_operation {
694% for item in values:
695   ${item.get_enum_name()},
696% endfor
697
698   /* Sentinels marking the last of each kind of operation. */
699% for item in lasts:
700   ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
701% endfor
702   ir_last_opcode = ir_quadop_${lasts[3].name}
703};""")
704
705   strings_template = mako.template.Template(copyright + """
706const char *const ir_expression_operation_strings[] = {
707% for item in values:
708   "${item.printable_name}",
709% endfor
710};
711
712const char *const ir_expression_operation_enum_strings[] = {
713% for item in values:
714   "${item.name}",
715% endfor
716};""")
717
718   constant_template = mako.template.Template("""\
719   switch (this->operation) {
720% for op in values:
721    % if op.c_expression is not None:
722${op.get_template()}
723
724    % endif
725% endfor
726   default:
727      /* FINISHME: Should handle all expression types. */
728      return NULL;
729   }
730""")
731
732   if sys.argv[1] == "enum":
733      lasts = [None, None, None, None]
734      for item in reversed(ir_expression_operation):
735         i = item.num_operands - 1
736         if lasts[i] is None:
737            lasts[i] = item
738
739      print(enum_template.render(values=ir_expression_operation,
740                                 lasts=lasts))
741   elif sys.argv[1] == "strings":
742      print(strings_template.render(values=ir_expression_operation))
743   elif sys.argv[1] == "constant":
744      print(constant_template.render(values=ir_expression_operation))
745