101e04c3fSmrg#
201e04c3fSmrg# Copyright (C) 2015 Intel Corporation
301e04c3fSmrg#
401e04c3fSmrg# Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg# copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg# to deal in the Software without restriction, including without limitation
701e04c3fSmrg# the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg# and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg# Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg#
1101e04c3fSmrg# The above copyright notice and this permission notice (including the next
1201e04c3fSmrg# paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg# Software.
1401e04c3fSmrg#
1501e04c3fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg# IN THE SOFTWARE.
2201e04c3fSmrg
2301e04c3fSmrgimport mako.template
2401e04c3fSmrgimport sys
2501e04c3fSmrg
2601e04c3fSmrgclass type(object):
2701e04c3fSmrg   def __init__(self, c_type, union_field, glsl_type):
2801e04c3fSmrg      self.c_type = c_type
2901e04c3fSmrg      self.union_field = union_field
3001e04c3fSmrg      self.glsl_type = glsl_type
3101e04c3fSmrg
3201e04c3fSmrg
3301e04c3fSmrgclass type_signature_iter(object):
3401e04c3fSmrg   """Basic iterator for a set of type signatures.  Various kinds of sequences of
3501e04c3fSmrg   types come in, and an iteration of type_signature objects come out.
3601e04c3fSmrg
3701e04c3fSmrg   """
3801e04c3fSmrg
3901e04c3fSmrg   def __init__(self, source_types, num_operands):
4001e04c3fSmrg      """Initialize an iterator from a sequence of input types and a number
4101e04c3fSmrg      operands.  This is for signatures where all the operands have the same
4201e04c3fSmrg      type and the result type of the operation is the same as the input type.
4301e04c3fSmrg
4401e04c3fSmrg      """
4501e04c3fSmrg      self.dest_type = None
4601e04c3fSmrg      self.source_types = source_types
4701e04c3fSmrg      self.num_operands = num_operands
4801e04c3fSmrg      self.i = 0
4901e04c3fSmrg
5001e04c3fSmrg   def __init__(self, dest_type, source_types, num_operands):
5101e04c3fSmrg      """Initialize an iterator from a result tpye, a sequence of input types and a
5201e04c3fSmrg      number operands.  This is for signatures where all the operands have the
5301e04c3fSmrg      same type but the result type of the operation is different from the
5401e04c3fSmrg      input type.
5501e04c3fSmrg
5601e04c3fSmrg      """
5701e04c3fSmrg      self.dest_type = dest_type
5801e04c3fSmrg      self.source_types = source_types
5901e04c3fSmrg      self.num_operands = num_operands
6001e04c3fSmrg      self.i = 0
6101e04c3fSmrg
6201e04c3fSmrg   def __iter__(self):
6301e04c3fSmrg      return self
6401e04c3fSmrg
6501e04c3fSmrg   def __next__(self):
6601e04c3fSmrg      if self.i < len(self.source_types):
6701e04c3fSmrg         i = self.i
6801e04c3fSmrg         self.i += 1
6901e04c3fSmrg
7001e04c3fSmrg         if self.dest_type is None:
7101e04c3fSmrg            dest_type = self.source_types[i]
7201e04c3fSmrg         else:
7301e04c3fSmrg            dest_type = self.dest_type
7401e04c3fSmrg
7501e04c3fSmrg         return (dest_type, self.num_operands * (self.source_types[i],))
7601e04c3fSmrg      else:
7701e04c3fSmrg         raise StopIteration()
7801e04c3fSmrg
7901e04c3fSmrg   next = __next__
8001e04c3fSmrg
8101e04c3fSmrg
8201e04c3fSmrguint_type = type("unsigned", "u", "GLSL_TYPE_UINT")
8301e04c3fSmrgint_type = type("int", "i", "GLSL_TYPE_INT")
8401e04c3fSmrguint64_type = type("uint64_t", "u64", "GLSL_TYPE_UINT64")
8501e04c3fSmrgint64_type = type("int64_t", "i64", "GLSL_TYPE_INT64")
8601e04c3fSmrgfloat_type = type("float", "f", "GLSL_TYPE_FLOAT")
8701e04c3fSmrgdouble_type = type("double", "d", "GLSL_TYPE_DOUBLE")
8801e04c3fSmrgbool_type = type("bool", "b", "GLSL_TYPE_BOOL")
8901e04c3fSmrg
9001e04c3fSmrgall_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type, bool_type)
9101e04c3fSmrgnumeric_types = (uint_type, int_type, float_type, double_type, uint64_type, int64_type)
9201e04c3fSmrgsigned_numeric_types = (int_type, float_type, double_type, int64_type)
9301e04c3fSmrginteger_types = (uint_type, int_type, uint64_type, int64_type)
9401e04c3fSmrgreal_types = (float_type, double_type)
9501e04c3fSmrg
9601e04c3fSmrg# This template is for operations that can have operands of a several
9701e04c3fSmrg# different types, and each type may or may not has a different C expression.
9801e04c3fSmrg# This is used by most operations.
9901e04c3fSmrgconstant_template_common = mako.template.Template("""\
10001e04c3fSmrg   case ${op.get_enum_name()}:
10101e04c3fSmrg      for (unsigned c = 0; c < op[0]->type->components(); c++) {
10201e04c3fSmrg         switch (op[0]->type->base_type) {
10301e04c3fSmrg    % for dst_type, src_types in op.signatures():
10401e04c3fSmrg         case ${src_types[0].glsl_type}:
10501e04c3fSmrg            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
10601e04c3fSmrg            break;
10701e04c3fSmrg    % endfor
10801e04c3fSmrg         default:
10901e04c3fSmrg            unreachable("invalid type");
11001e04c3fSmrg         }
11101e04c3fSmrg      }
11201e04c3fSmrg      break;""")
11301e04c3fSmrg
11401e04c3fSmrg# This template is for binary operations that can operate on some combination
11501e04c3fSmrg# of scalar and vector operands.
11601e04c3fSmrgconstant_template_vector_scalar = mako.template.Template("""\
11701e04c3fSmrg   case ${op.get_enum_name()}:
11801e04c3fSmrg    % if "mixed" in op.flags:
11901e04c3fSmrg        % for i in range(op.num_operands):
12001e04c3fSmrg      assert(op[${i}]->type->base_type == ${op.source_types[0].glsl_type} ||
12101e04c3fSmrg            % for src_type in op.source_types[1:-1]:
12201e04c3fSmrg             op[${i}]->type->base_type == ${src_type.glsl_type} ||
12301e04c3fSmrg            % endfor
12401e04c3fSmrg             op[${i}]->type->base_type == ${op.source_types[-1].glsl_type});
12501e04c3fSmrg        % endfor
12601e04c3fSmrg    % else:
12701e04c3fSmrg      assert(op[0]->type == op[1]->type || op0_scalar || op1_scalar);
12801e04c3fSmrg    % endif
12901e04c3fSmrg      for (unsigned c = 0, c0 = 0, c1 = 0;
13001e04c3fSmrg           c < components;
13101e04c3fSmrg           c0 += c0_inc, c1 += c1_inc, c++) {
13201e04c3fSmrg
13301e04c3fSmrg         switch (op[0]->type->base_type) {
13401e04c3fSmrg    % for dst_type, src_types in op.signatures():
13501e04c3fSmrg         case ${src_types[0].glsl_type}:
13601e04c3fSmrg            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
13701e04c3fSmrg            break;
13801e04c3fSmrg    % endfor
13901e04c3fSmrg         default:
14001e04c3fSmrg            unreachable("invalid type");
14101e04c3fSmrg         }
14201e04c3fSmrg      }
14301e04c3fSmrg      break;""")
14401e04c3fSmrg
14501e04c3fSmrg# This template is for multiplication.  It is unique because it has to support
14601e04c3fSmrg# matrix * vector and matrix * matrix operations, and those are just different.
14701e04c3fSmrgconstant_template_mul = mako.template.Template("""\
14801e04c3fSmrg   case ${op.get_enum_name()}:
14901e04c3fSmrg      /* Check for equal types, or unequal types involving scalars */
15001e04c3fSmrg      if ((op[0]->type == op[1]->type && !op[0]->type->is_matrix())
15101e04c3fSmrg          || op0_scalar || op1_scalar) {
15201e04c3fSmrg         for (unsigned c = 0, c0 = 0, c1 = 0;
15301e04c3fSmrg              c < components;
15401e04c3fSmrg              c0 += c0_inc, c1 += c1_inc, c++) {
15501e04c3fSmrg
15601e04c3fSmrg            switch (op[0]->type->base_type) {
15701e04c3fSmrg    % for dst_type, src_types in op.signatures():
15801e04c3fSmrg            case ${src_types[0].glsl_type}:
15901e04c3fSmrg               data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c0", "c1", "c2"))};
16001e04c3fSmrg               break;
16101e04c3fSmrg    % endfor
16201e04c3fSmrg            default:
16301e04c3fSmrg               unreachable("invalid type");
16401e04c3fSmrg            }
16501e04c3fSmrg         }
16601e04c3fSmrg      } else {
16701e04c3fSmrg         assert(op[0]->type->is_matrix() || op[1]->type->is_matrix());
16801e04c3fSmrg
16901e04c3fSmrg         /* Multiply an N-by-M matrix with an M-by-P matrix.  Since either
17001e04c3fSmrg          * matrix can be a GLSL vector, either N or P can be 1.
17101e04c3fSmrg          *
17201e04c3fSmrg          * For vec*mat, the vector is treated as a row vector.  This
17301e04c3fSmrg          * means the vector is a 1-row x M-column matrix.
17401e04c3fSmrg          *
17501e04c3fSmrg          * For mat*vec, the vector is treated as a column vector.  Since
17601e04c3fSmrg          * matrix_columns is 1 for vectors, this just works.
17701e04c3fSmrg          */
17801e04c3fSmrg         const unsigned n = op[0]->type->is_vector()
17901e04c3fSmrg            ? 1 : op[0]->type->vector_elements;
18001e04c3fSmrg         const unsigned m = op[1]->type->vector_elements;
18101e04c3fSmrg         const unsigned p = op[1]->type->matrix_columns;
18201e04c3fSmrg         for (unsigned j = 0; j < p; j++) {
18301e04c3fSmrg            for (unsigned i = 0; i < n; i++) {
18401e04c3fSmrg               for (unsigned k = 0; k < m; k++) {
18501e04c3fSmrg                  if (op[0]->type->is_double())
18601e04c3fSmrg                     data.d[i+n*j] += op[0]->value.d[i+n*k]*op[1]->value.d[k+m*j];
18701e04c3fSmrg                  else
18801e04c3fSmrg                     data.f[i+n*j] += op[0]->value.f[i+n*k]*op[1]->value.f[k+m*j];
18901e04c3fSmrg               }
19001e04c3fSmrg            }
19101e04c3fSmrg         }
19201e04c3fSmrg      }
19301e04c3fSmrg      break;""")
19401e04c3fSmrg
19501e04c3fSmrg# This template is for operations that are horizontal and either have only a
19601e04c3fSmrg# single type or the implementation for all types is identical.  That is, the
19701e04c3fSmrg# operation consumes a vector and produces a scalar.
19801e04c3fSmrgconstant_template_horizontal_single_implementation = mako.template.Template("""\
19901e04c3fSmrg   case ${op.get_enum_name()}:
20001e04c3fSmrg      data.${op.dest_type.union_field}[0] = ${op.c_expression['default']};
20101e04c3fSmrg      break;""")
20201e04c3fSmrg
20301e04c3fSmrg# This template is for operations that are horizontal and do not assign the
20401e04c3fSmrg# result.  The various unpack operations are examples.
20501e04c3fSmrgconstant_template_horizontal_nonassignment = mako.template.Template("""\
20601e04c3fSmrg   case ${op.get_enum_name()}:
20701e04c3fSmrg      ${op.c_expression['default']};
20801e04c3fSmrg      break;""")
20901e04c3fSmrg
21001e04c3fSmrg# This template is for binary operations that are horizontal.  That is, the
21101e04c3fSmrg# operation consumes a vector and produces a scalar.
21201e04c3fSmrgconstant_template_horizontal = mako.template.Template("""\
21301e04c3fSmrg   case ${op.get_enum_name()}:
21401e04c3fSmrg      switch (op[0]->type->base_type) {
21501e04c3fSmrg    % for dst_type, src_types in op.signatures():
21601e04c3fSmrg      case ${src_types[0].glsl_type}:
21701e04c3fSmrg         data.${dst_type.union_field}[0] = ${op.get_c_expression(src_types)};
21801e04c3fSmrg         break;
21901e04c3fSmrg    % endfor
22001e04c3fSmrg      default:
22101e04c3fSmrg         unreachable("invalid type");
22201e04c3fSmrg      }
22301e04c3fSmrg      break;""")
22401e04c3fSmrg
22501e04c3fSmrg# This template is for ir_binop_vector_extract.
22601e04c3fSmrgconstant_template_vector_extract = mako.template.Template("""\
22701e04c3fSmrg   case ${op.get_enum_name()}: {
22801e04c3fSmrg      const int c = CLAMP(op[1]->value.i[0], 0,
22901e04c3fSmrg                          (int) op[0]->type->vector_elements - 1);
23001e04c3fSmrg
23101e04c3fSmrg      switch (op[0]->type->base_type) {
23201e04c3fSmrg    % for dst_type, src_types in op.signatures():
23301e04c3fSmrg      case ${src_types[0].glsl_type}:
23401e04c3fSmrg         data.${dst_type.union_field}[0] = op[0]->value.${src_types[0].union_field}[c];
23501e04c3fSmrg         break;
23601e04c3fSmrg    % endfor
23701e04c3fSmrg      default:
23801e04c3fSmrg         unreachable("invalid type");
23901e04c3fSmrg      }
24001e04c3fSmrg      break;
24101e04c3fSmrg   }""")
24201e04c3fSmrg
24301e04c3fSmrg# This template is for ir_triop_vector_insert.
24401e04c3fSmrgconstant_template_vector_insert = mako.template.Template("""\
24501e04c3fSmrg   case ${op.get_enum_name()}: {
24601e04c3fSmrg      const unsigned idx = op[2]->value.u[0];
24701e04c3fSmrg
24801e04c3fSmrg      memcpy(&data, &op[0]->value, sizeof(data));
24901e04c3fSmrg
2507ec681f3Smrg      switch (return_type->base_type) {
25101e04c3fSmrg    % for dst_type, src_types in op.signatures():
25201e04c3fSmrg      case ${src_types[0].glsl_type}:
25301e04c3fSmrg         data.${dst_type.union_field}[idx] = op[1]->value.${src_types[0].union_field}[0];
25401e04c3fSmrg         break;
25501e04c3fSmrg    % endfor
25601e04c3fSmrg      default:
25701e04c3fSmrg         unreachable("invalid type");
25801e04c3fSmrg      }
25901e04c3fSmrg      break;
26001e04c3fSmrg   }""")
26101e04c3fSmrg
26201e04c3fSmrg# This template is for ir_quadop_vector.
26301e04c3fSmrgconstant_template_vector = mako.template.Template("""\
26401e04c3fSmrg   case ${op.get_enum_name()}:
2657ec681f3Smrg      for (unsigned c = 0; c < return_type->vector_elements; c++) {
2667ec681f3Smrg         switch (return_type->base_type) {
26701e04c3fSmrg    % for dst_type, src_types in op.signatures():
26801e04c3fSmrg         case ${src_types[0].glsl_type}:
26901e04c3fSmrg            data.${dst_type.union_field}[c] = op[c]->value.${src_types[0].union_field}[0];
27001e04c3fSmrg            break;
27101e04c3fSmrg    % endfor
27201e04c3fSmrg         default:
27301e04c3fSmrg            unreachable("invalid type");
27401e04c3fSmrg         }
27501e04c3fSmrg      }
27601e04c3fSmrg      break;""")
27701e04c3fSmrg
27801e04c3fSmrg# This template is for ir_triop_lrp.
27901e04c3fSmrgconstant_template_lrp = mako.template.Template("""\
28001e04c3fSmrg   case ${op.get_enum_name()}: {
28101e04c3fSmrg      assert(op[0]->type->is_float() || op[0]->type->is_double());
28201e04c3fSmrg      assert(op[1]->type->is_float() || op[1]->type->is_double());
28301e04c3fSmrg      assert(op[2]->type->is_float() || op[2]->type->is_double());
28401e04c3fSmrg
28501e04c3fSmrg      unsigned c2_inc = op[2]->type->is_scalar() ? 0 : 1;
28601e04c3fSmrg      for (unsigned c = 0, c2 = 0; c < components; c2 += c2_inc, c++) {
2877ec681f3Smrg         switch (return_type->base_type) {
28801e04c3fSmrg    % for dst_type, src_types in op.signatures():
28901e04c3fSmrg         case ${src_types[0].glsl_type}:
29001e04c3fSmrg            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types, ("c", "c", "c2"))};
29101e04c3fSmrg            break;
29201e04c3fSmrg    % endfor
29301e04c3fSmrg         default:
29401e04c3fSmrg            unreachable("invalid type");
29501e04c3fSmrg         }
29601e04c3fSmrg      }
29701e04c3fSmrg      break;
29801e04c3fSmrg   }""")
29901e04c3fSmrg
30001e04c3fSmrg# This template is for ir_triop_csel.  This expression is really unique
30101e04c3fSmrg# because not all of the operands are the same type, and the second operand
30201e04c3fSmrg# determines the type of the expression (instead of the first).
30301e04c3fSmrgconstant_template_csel = mako.template.Template("""\
30401e04c3fSmrg   case ${op.get_enum_name()}:
30501e04c3fSmrg      for (unsigned c = 0; c < components; c++) {
3067ec681f3Smrg         switch (return_type->base_type) {
30701e04c3fSmrg    % for dst_type, src_types in op.signatures():
30801e04c3fSmrg         case ${src_types[1].glsl_type}:
30901e04c3fSmrg            data.${dst_type.union_field}[c] = ${op.get_c_expression(src_types)};
31001e04c3fSmrg            break;
31101e04c3fSmrg    % endfor
31201e04c3fSmrg         default:
31301e04c3fSmrg            unreachable("invalid type");
31401e04c3fSmrg         }
31501e04c3fSmrg      }
31601e04c3fSmrg      break;""")
31701e04c3fSmrg
31801e04c3fSmrg
31901e04c3fSmrgvector_scalar_operation = "vector-scalar"
32001e04c3fSmrghorizontal_operation = "horizontal"
32101e04c3fSmrgtypes_identical_operation = "identical"
32201e04c3fSmrgnon_assign_operation = "nonassign"
32301e04c3fSmrgmixed_type_operation = "mixed"
32401e04c3fSmrg
32501e04c3fSmrgclass operation(object):
32601e04c3fSmrg   def __init__(self, name, num_operands, printable_name = None, source_types = None, dest_type = None, c_expression = None, flags = None, all_signatures = None):
32701e04c3fSmrg      self.name = name
32801e04c3fSmrg      self.num_operands = num_operands
32901e04c3fSmrg
33001e04c3fSmrg      if printable_name is None:
33101e04c3fSmrg         self.printable_name = name
33201e04c3fSmrg      else:
33301e04c3fSmrg         self.printable_name = printable_name
33401e04c3fSmrg
33501e04c3fSmrg      self.all_signatures = all_signatures
33601e04c3fSmrg
33701e04c3fSmrg      if source_types is None:
33801e04c3fSmrg         self.source_types = tuple()
33901e04c3fSmrg      else:
34001e04c3fSmrg         self.source_types = source_types
34101e04c3fSmrg
34201e04c3fSmrg      self.dest_type = dest_type
34301e04c3fSmrg
34401e04c3fSmrg      if c_expression is None:
34501e04c3fSmrg         self.c_expression = None
34601e04c3fSmrg      elif isinstance(c_expression, str):
34701e04c3fSmrg         self.c_expression = {'default': c_expression}
34801e04c3fSmrg      else:
34901e04c3fSmrg         self.c_expression = c_expression
35001e04c3fSmrg
35101e04c3fSmrg      if flags is None:
35201e04c3fSmrg         self.flags = frozenset()
35301e04c3fSmrg      elif isinstance(flags, str):
35401e04c3fSmrg         self.flags = frozenset([flags])
35501e04c3fSmrg      else:
35601e04c3fSmrg         self.flags = frozenset(flags)
35701e04c3fSmrg
35801e04c3fSmrg
35901e04c3fSmrg   def get_enum_name(self):
36001e04c3fSmrg      return "ir_{0}op_{1}".format(("un", "bin", "tri", "quad")[self.num_operands-1], self.name)
36101e04c3fSmrg
36201e04c3fSmrg
36301e04c3fSmrg   def get_template(self):
36401e04c3fSmrg      if self.c_expression is None:
36501e04c3fSmrg         return None
36601e04c3fSmrg
36701e04c3fSmrg      if horizontal_operation in self.flags:
36801e04c3fSmrg         if non_assign_operation in self.flags:
36901e04c3fSmrg            return constant_template_horizontal_nonassignment.render(op=self)
37001e04c3fSmrg         elif types_identical_operation in self.flags:
37101e04c3fSmrg            return constant_template_horizontal_single_implementation.render(op=self)
37201e04c3fSmrg         else:
37301e04c3fSmrg            return constant_template_horizontal.render(op=self)
37401e04c3fSmrg
37501e04c3fSmrg      if self.num_operands == 2:
37601e04c3fSmrg         if self.name == "mul":
37701e04c3fSmrg            return constant_template_mul.render(op=self)
37801e04c3fSmrg         elif self.name == "vector_extract":
37901e04c3fSmrg            return constant_template_vector_extract.render(op=self)
38001e04c3fSmrg         elif vector_scalar_operation in self.flags:
38101e04c3fSmrg            return constant_template_vector_scalar.render(op=self)
38201e04c3fSmrg      elif self.num_operands == 3:
38301e04c3fSmrg         if self.name == "vector_insert":
38401e04c3fSmrg            return constant_template_vector_insert.render(op=self)
38501e04c3fSmrg         elif self.name == "lrp":
38601e04c3fSmrg            return constant_template_lrp.render(op=self)
38701e04c3fSmrg         elif self.name == "csel":
38801e04c3fSmrg            return constant_template_csel.render(op=self)
38901e04c3fSmrg      elif self.num_operands == 4:
39001e04c3fSmrg         if self.name == "vector":
39101e04c3fSmrg            return constant_template_vector.render(op=self)
39201e04c3fSmrg
39301e04c3fSmrg      return constant_template_common.render(op=self)
39401e04c3fSmrg
39501e04c3fSmrg
39601e04c3fSmrg   def get_c_expression(self, types, indices=("c", "c", "c")):
39701e04c3fSmrg      src0 = "op[0]->value.{0}[{1}]".format(types[0].union_field, indices[0])
39801e04c3fSmrg      src1 = "op[1]->value.{0}[{1}]".format(types[1].union_field, indices[1]) if len(types) >= 2 else "ERROR"
39901e04c3fSmrg      src2 = "op[2]->value.{0}[{1}]".format(types[2].union_field, indices[2]) if len(types) >= 3 else "ERROR"
40001e04c3fSmrg      src3 = "op[3]->value.{0}[c]".format(types[3].union_field) if len(types) >= 4 else "ERROR"
40101e04c3fSmrg
40201e04c3fSmrg      expr = self.c_expression[types[0].union_field] if types[0].union_field in self.c_expression else self.c_expression['default']
40301e04c3fSmrg
40401e04c3fSmrg      return expr.format(src0=src0,
40501e04c3fSmrg                         src1=src1,
40601e04c3fSmrg                         src2=src2,
40701e04c3fSmrg                         src3=src3)
40801e04c3fSmrg
40901e04c3fSmrg
41001e04c3fSmrg   def signatures(self):
41101e04c3fSmrg      if self.all_signatures is not None:
41201e04c3fSmrg         return self.all_signatures
41301e04c3fSmrg      else:
41401e04c3fSmrg         return type_signature_iter(self.dest_type, self.source_types, self.num_operands)
41501e04c3fSmrg
41601e04c3fSmrg
41701e04c3fSmrgir_expression_operation = [
41801e04c3fSmrg   operation("bit_not", 1, printable_name="~", source_types=integer_types, c_expression="~ {src0}"),
41901e04c3fSmrg   operation("logic_not", 1, printable_name="!", source_types=(bool_type,), c_expression="!{src0}"),
4207ec681f3Smrg   operation("neg", 1, source_types=numeric_types, c_expression={'u': "-((int) {src0})", 'u64': "-((int64_t) {src0})", 'default': "-{src0}"}),
42101e04c3fSmrg   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}"}),
42201e04c3fSmrg   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)"}),
42301e04c3fSmrg   operation("rcp", 1, source_types=real_types, c_expression={'f': "1.0F / {src0}", 'd': "1.0 / {src0}"}),
42401e04c3fSmrg   operation("rsq", 1, source_types=real_types, c_expression={'f': "1.0F / sqrtf({src0})", 'd': "1.0 / sqrt({src0})"}),
42501e04c3fSmrg   operation("sqrt", 1, source_types=real_types, c_expression={'f': "sqrtf({src0})", 'd': "sqrt({src0})"}),
42601e04c3fSmrg   operation("exp", 1, source_types=(float_type,), c_expression="expf({src0})"),         # Log base e on gentype
42701e04c3fSmrg   operation("log", 1, source_types=(float_type,), c_expression="logf({src0})"),         # Natural log on gentype
42801e04c3fSmrg   operation("exp2", 1, source_types=(float_type,), c_expression="exp2f({src0})"),
42901e04c3fSmrg   operation("log2", 1, source_types=(float_type,), c_expression="log2f({src0})"),
43001e04c3fSmrg
43101e04c3fSmrg   # Float-to-integer conversion.
43201e04c3fSmrg   operation("f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="(int) {src0}"),
43301e04c3fSmrg   # Float-to-unsigned conversion.
43401e04c3fSmrg   operation("f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="(unsigned) {src0}"),
43501e04c3fSmrg   # Integer-to-float conversion.
43601e04c3fSmrg   operation("i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="(float) {src0}"),
43701e04c3fSmrg   # Float-to-boolean conversion
43801e04c3fSmrg   operation("f2b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0F ? true : false"),
43901e04c3fSmrg   # Boolean-to-float conversion
44001e04c3fSmrg   operation("b2f", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
4417ec681f3Smrg   # Boolean-to-float16 conversion
4427ec681f3Smrg   operation("b2f16", 1, source_types=(bool_type,), dest_type=float_type, c_expression="{src0} ? 1.0F : 0.0F"),
44301e04c3fSmrg   # int-to-boolean conversion
44401e04c3fSmrg   operation("i2b", 1, source_types=(uint_type, int_type), dest_type=bool_type, c_expression="{src0} ? true : false"),
44501e04c3fSmrg   # Boolean-to-int conversion
44601e04c3fSmrg   operation("b2i", 1, source_types=(bool_type,), dest_type=int_type, c_expression="{src0} ? 1 : 0"),
44701e04c3fSmrg   # Unsigned-to-float conversion.
44801e04c3fSmrg   operation("u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="(float) {src0}"),
44901e04c3fSmrg   # Integer-to-unsigned conversion.
45001e04c3fSmrg   operation("i2u", 1, source_types=(int_type,), dest_type=uint_type, c_expression="{src0}"),
45101e04c3fSmrg   # Unsigned-to-integer conversion.
45201e04c3fSmrg   operation("u2i", 1, source_types=(uint_type,), dest_type=int_type, c_expression="{src0}"),
45301e04c3fSmrg   # Double-to-float conversion.
45401e04c3fSmrg   operation("d2f", 1, source_types=(double_type,), dest_type=float_type, c_expression="{src0}"),
45501e04c3fSmrg   # Float-to-double conversion.
45601e04c3fSmrg   operation("f2d", 1, source_types=(float_type,), dest_type=double_type, c_expression="{src0}"),
4577ec681f3Smrg   # Half-float conversions. These all operate on and return float types,
4587ec681f3Smrg   # since the framework expands half to full float before calling in.  We
4597ec681f3Smrg   # still have to handle them here so that we can constant propagate through
4607ec681f3Smrg   # them, but they are no-ops.
4617ec681f3Smrg   operation("f2f16", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
4627ec681f3Smrg   operation("f2fmp", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
4637ec681f3Smrg   operation("f162f", 1, source_types=(float_type,), dest_type=float_type, c_expression="{src0}"),
4647ec681f3Smrg   # int16<->int32 conversion.
4657ec681f3Smrg   operation("i2i", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"),
4667ec681f3Smrg   operation("i2imp", 1, source_types=(int_type,), dest_type=int_type, c_expression="{src0}"),
4677ec681f3Smrg   operation("u2u", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"),
4687ec681f3Smrg   operation("u2ump", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="{src0}"),
46901e04c3fSmrg   # Double-to-integer conversion.
47001e04c3fSmrg   operation("d2i", 1, source_types=(double_type,), dest_type=int_type, c_expression="{src0}"),
47101e04c3fSmrg   # Integer-to-double conversion.
47201e04c3fSmrg   operation("i2d", 1, source_types=(int_type,), dest_type=double_type, c_expression="{src0}"),
47301e04c3fSmrg   # Double-to-unsigned conversion.
47401e04c3fSmrg   operation("d2u", 1, source_types=(double_type,), dest_type=uint_type, c_expression="{src0}"),
47501e04c3fSmrg   # Unsigned-to-double conversion.
47601e04c3fSmrg   operation("u2d", 1, source_types=(uint_type,), dest_type=double_type, c_expression="{src0}"),
47701e04c3fSmrg   # Double-to-boolean conversion.
47801e04c3fSmrg   operation("d2b", 1, source_types=(double_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
4797ec681f3Smrg   # Float16-to-boolean conversion.
4807ec681f3Smrg   operation("f162b", 1, source_types=(float_type,), dest_type=bool_type, c_expression="{src0} != 0.0"),
48101e04c3fSmrg   # 'Bit-identical int-to-float "conversion"
48201e04c3fSmrg   operation("bitcast_i2f", 1, source_types=(int_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
48301e04c3fSmrg   # 'Bit-identical float-to-int "conversion"
48401e04c3fSmrg   operation("bitcast_f2i", 1, source_types=(float_type,), dest_type=int_type, c_expression="bitcast_f2u({src0})"),
48501e04c3fSmrg   # 'Bit-identical uint-to-float "conversion"
48601e04c3fSmrg   operation("bitcast_u2f", 1, source_types=(uint_type,), dest_type=float_type, c_expression="bitcast_u2f({src0})"),
48701e04c3fSmrg   # 'Bit-identical float-to-uint "conversion"
48801e04c3fSmrg   operation("bitcast_f2u", 1, source_types=(float_type,), dest_type=uint_type, c_expression="bitcast_f2u({src0})"),
48901e04c3fSmrg   # Bit-identical u64-to-double "conversion"
49001e04c3fSmrg   operation("bitcast_u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="bitcast_u642d({src0})"),
49101e04c3fSmrg   # Bit-identical i64-to-double "conversion"
49201e04c3fSmrg   operation("bitcast_i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="bitcast_i642d({src0})"),
49301e04c3fSmrg   # Bit-identical double-to_u64 "conversion"
49401e04c3fSmrg   operation("bitcast_d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="bitcast_d2u64({src0})"),
49501e04c3fSmrg   # Bit-identical double-to-i64 "conversion"
49601e04c3fSmrg   operation("bitcast_d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="bitcast_d2i64({src0})"),
49701e04c3fSmrg   # i64-to-i32 conversion
49801e04c3fSmrg   operation("i642i", 1, source_types=(int64_type,), dest_type=int_type, c_expression="{src0}"),
49901e04c3fSmrg   # ui64-to-i32 conversion
50001e04c3fSmrg   operation("u642i", 1, source_types=(uint64_type,), dest_type=int_type, c_expression="{src0}"),
50101e04c3fSmrg   operation("i642u", 1, source_types=(int64_type,), dest_type=uint_type, c_expression="{src0}"),
50201e04c3fSmrg   operation("u642u", 1, source_types=(uint64_type,), dest_type=uint_type, c_expression="{src0}"),
50301e04c3fSmrg   operation("i642b", 1, source_types=(int64_type,), dest_type=bool_type, c_expression="{src0} != 0"),
50401e04c3fSmrg   operation("i642f", 1, source_types=(int64_type,), dest_type=float_type, c_expression="{src0}"),
50501e04c3fSmrg   operation("u642f", 1, source_types=(uint64_type,), dest_type=float_type, c_expression="{src0}"),
50601e04c3fSmrg   operation("i642d", 1, source_types=(int64_type,), dest_type=double_type, c_expression="{src0}"),
50701e04c3fSmrg   operation("u642d", 1, source_types=(uint64_type,), dest_type=double_type, c_expression="{src0}"),
50801e04c3fSmrg   operation("i2i64", 1, source_types=(int_type,), dest_type=int64_type, c_expression="{src0}"),
50901e04c3fSmrg   operation("u2i64", 1, source_types=(uint_type,), dest_type=int64_type, c_expression="{src0}"),
51001e04c3fSmrg   operation("b2i64", 1, source_types=(bool_type,), dest_type=int64_type, c_expression="{src0}"),
51101e04c3fSmrg   operation("f2i64", 1, source_types=(float_type,), dest_type=int64_type, c_expression="{src0}"),
51201e04c3fSmrg   operation("d2i64", 1, source_types=(double_type,), dest_type=int64_type, c_expression="{src0}"),
51301e04c3fSmrg   operation("i2u64", 1, source_types=(int_type,), dest_type=uint64_type, c_expression="{src0}"),
51401e04c3fSmrg   operation("u2u64", 1, source_types=(uint_type,), dest_type=uint64_type, c_expression="{src0}"),
51501e04c3fSmrg   operation("f2u64", 1, source_types=(float_type,), dest_type=uint64_type, c_expression="{src0}"),
51601e04c3fSmrg   operation("d2u64", 1, source_types=(double_type,), dest_type=uint64_type, c_expression="{src0}"),
51701e04c3fSmrg   operation("u642i64", 1, source_types=(uint64_type,), dest_type=int64_type, c_expression="{src0}"),
51801e04c3fSmrg   operation("i642u64", 1, source_types=(int64_type,), dest_type=uint64_type, c_expression="{src0}"),
51901e04c3fSmrg
52001e04c3fSmrg
52101e04c3fSmrg   # Unary floating-point rounding operations.
52201e04c3fSmrg   operation("trunc", 1, source_types=real_types, c_expression={'f': "truncf({src0})", 'd': "trunc({src0})"}),
52301e04c3fSmrg   operation("ceil", 1, source_types=real_types, c_expression={'f': "ceilf({src0})", 'd': "ceil({src0})"}),
52401e04c3fSmrg   operation("floor", 1, source_types=real_types, c_expression={'f': "floorf({src0})", 'd': "floor({src0})"}),
52501e04c3fSmrg   operation("fract", 1, source_types=real_types, c_expression={'f': "{src0} - floorf({src0})", 'd': "{src0} - floor({src0})"}),
52601e04c3fSmrg   operation("round_even", 1, source_types=real_types, c_expression={'f': "_mesa_roundevenf({src0})", 'd': "_mesa_roundeven({src0})"}),
52701e04c3fSmrg
52801e04c3fSmrg   # Trigonometric operations.
52901e04c3fSmrg   operation("sin", 1, source_types=(float_type,), c_expression="sinf({src0})"),
53001e04c3fSmrg   operation("cos", 1, source_types=(float_type,), c_expression="cosf({src0})"),
5317ec681f3Smrg   operation("atan", 1, source_types=(float_type,), c_expression="atan({src0})"),
53201e04c3fSmrg
53301e04c3fSmrg   # Partial derivatives.
53401e04c3fSmrg   operation("dFdx", 1, source_types=(float_type,), c_expression="0.0f"),
53501e04c3fSmrg   operation("dFdx_coarse", 1, printable_name="dFdxCoarse", source_types=(float_type,), c_expression="0.0f"),
53601e04c3fSmrg   operation("dFdx_fine", 1, printable_name="dFdxFine", source_types=(float_type,), c_expression="0.0f"),
53701e04c3fSmrg   operation("dFdy", 1, source_types=(float_type,), c_expression="0.0f"),
53801e04c3fSmrg   operation("dFdy_coarse", 1, printable_name="dFdyCoarse", source_types=(float_type,), c_expression="0.0f"),
53901e04c3fSmrg   operation("dFdy_fine", 1, printable_name="dFdyFine", source_types=(float_type,), c_expression="0.0f"),
54001e04c3fSmrg
54101e04c3fSmrg   # Floating point pack and unpack operations.
54201e04c3fSmrg   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),
54301e04c3fSmrg   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),
54401e04c3fSmrg   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),
54501e04c3fSmrg   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),
54601e04c3fSmrg   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),
54701e04c3fSmrg   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))),
54801e04c3fSmrg   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))),
54901e04c3fSmrg   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))),
55001e04c3fSmrg   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))),
55101e04c3fSmrg   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))),
55201e04c3fSmrg
55301e04c3fSmrg   # Bit operations, part of ARB_gpu_shader5.
55401e04c3fSmrg   operation("bitfield_reverse", 1, source_types=(uint_type, int_type), c_expression="bitfield_reverse({src0})"),
55501e04c3fSmrg   operation("bit_count", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="util_bitcount({src0})"),
55601e04c3fSmrg   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})"}),
55701e04c3fSmrg   operation("find_lsb", 1, source_types=(uint_type, int_type), dest_type=int_type, c_expression="find_msb_uint({src0} & -{src0})"),
5587ec681f3Smrg   operation("clz", 1, source_types=(uint_type,), dest_type=uint_type, c_expression="(unsigned)(31 - find_msb_uint({src0}))"),
55901e04c3fSmrg
56001e04c3fSmrg   operation("saturate", 1, printable_name="sat", source_types=(float_type,), c_expression="CLAMP({src0}, 0.0f, 1.0f)"),
56101e04c3fSmrg
56201e04c3fSmrg   # Double packing, part of ARB_gpu_shader_fp64.
5637ec681f3Smrg   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))),
5647ec681f3Smrg   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))),
56501e04c3fSmrg
56601e04c3fSmrg   # Sampler/Image packing, part of ARB_bindless_texture.
5677ec681f3Smrg   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))),
5687ec681f3Smrg   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))),
5697ec681f3Smrg   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))),
5707ec681f3Smrg   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))),
57101e04c3fSmrg
57201e04c3fSmrg   operation("frexp_sig", 1),
57301e04c3fSmrg   operation("frexp_exp", 1),
57401e04c3fSmrg
57501e04c3fSmrg   operation("subroutine_to_int", 1),
57601e04c3fSmrg
57701e04c3fSmrg   # Interpolate fs input at centroid
57801e04c3fSmrg   #
57901e04c3fSmrg   # operand0 is the fs input.
58001e04c3fSmrg   operation("interpolate_at_centroid", 1),
58101e04c3fSmrg
58201e04c3fSmrg   # Ask the driver for the total size of a buffer block.
58301e04c3fSmrg   # operand0 is the ir_constant buffer block index in the linked shader.
58401e04c3fSmrg   operation("get_buffer_size", 1),
58501e04c3fSmrg
58601e04c3fSmrg   # Calculate length of an unsized array inside a buffer block.
58701e04c3fSmrg   # This opcode is going to be replaced in a lowering pass inside
58801e04c3fSmrg   # the linker.
58901e04c3fSmrg   #
59001e04c3fSmrg   # operand0 is the unsized array's ir_value for the calculation
59101e04c3fSmrg   # of its length.
59201e04c3fSmrg   operation("ssbo_unsized_array_length", 1),
59301e04c3fSmrg
5947ec681f3Smrg   # Calculate length of an implicitly sized array.
5957ec681f3Smrg   # This opcode is going to be replaced with a constant expression at link
5967ec681f3Smrg   # time.
5977ec681f3Smrg   operation("implicitly_sized_array_length", 1),
5987ec681f3Smrg
59901e04c3fSmrg   # 64-bit integer packing ops.
6007ec681f3Smrg   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))),
6017ec681f3Smrg   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))),
6027ec681f3Smrg   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))),
6037ec681f3Smrg   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))),
60401e04c3fSmrg
60501e04c3fSmrg   operation("add", 2, printable_name="+", source_types=numeric_types, c_expression="{src0} + {src1}", flags=vector_scalar_operation),
60601e04c3fSmrg   operation("sub", 2, printable_name="-", source_types=numeric_types, c_expression="{src0} - {src1}", flags=vector_scalar_operation),
6077ec681f3Smrg   operation("add_sat", 2, printable_name="add_sat", source_types=integer_types, c_expression={
6087ec681f3Smrg      'u': "({src0} + {src1}) < {src0} ? UINT32_MAX : ({src0} + {src1})",
6097ec681f3Smrg      'i': "iadd_saturate({src0}, {src1})",
6107ec681f3Smrg      'u64': "({src0} + {src1}) < {src0} ? UINT64_MAX : ({src0} + {src1})",
6117ec681f3Smrg      'i64': "iadd64_saturate({src0}, {src1})"
6127ec681f3Smrg   }),
6137ec681f3Smrg   operation("sub_sat", 2, printable_name="sub_sat", source_types=integer_types, c_expression={
6147ec681f3Smrg      'u': "({src1} > {src0}) ? 0 : {src0} - {src1}",
6157ec681f3Smrg      'i': "isub_saturate({src0}, {src1})",
6167ec681f3Smrg      'u64': "({src1} > {src0}) ? 0 : {src0} - {src1}",
6177ec681f3Smrg      'i64': "isub64_saturate({src0}, {src1})"
6187ec681f3Smrg   }),
6197ec681f3Smrg   operation("abs_sub", 2, printable_name="abs_sub", source_types=integer_types, c_expression={
6207ec681f3Smrg      'u': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
6217ec681f3Smrg      'i': "({src1} > {src0}) ? (unsigned){src1} - (unsigned){src0} : (unsigned){src0} - (unsigned){src1}",
6227ec681f3Smrg      'u64': "({src1} > {src0}) ? {src1} - {src0} : {src0} - {src1}",
6237ec681f3Smrg      'i64': "({src1} > {src0}) ? (uint64_t){src1} - (uint64_t){src0} : (uint64_t){src0} - (uint64_t){src1}",
6247ec681f3Smrg   }),
6257ec681f3Smrg   operation("avg", 2, printable_name="average", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} & {src1}) & 1)"),
6267ec681f3Smrg   operation("avg_round", 2, printable_name="average_rounded", source_types=integer_types, c_expression="({src0} >> 1) + ({src1} >> 1) + (({src0} | {src1}) & 1)"),
6277ec681f3Smrg
62801e04c3fSmrg   # "Floating-point or low 32-bit integer multiply."
62901e04c3fSmrg   operation("mul", 2, printable_name="*", source_types=numeric_types, c_expression="{src0} * {src1}"),
6307ec681f3Smrg   operation("mul_32x16", 2, printable_name="*", source_types=(uint_type, int_type), c_expression={
6317ec681f3Smrg      'u': "{src0} * (uint16_t){src1}",
6327ec681f3Smrg      'i': "{src0} * (int16_t){src0}"
6337ec681f3Smrg   }),
63401e04c3fSmrg   operation("imul_high", 2),       # Calculates the high 32-bits of a 64-bit multiply.
63501e04c3fSmrg   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),
63601e04c3fSmrg
63701e04c3fSmrg   # Returns the carry resulting from the addition of the two arguments.
63801e04c3fSmrg   operation("carry", 2),
63901e04c3fSmrg
64001e04c3fSmrg   # Returns the borrow resulting from the subtraction of the second argument
64101e04c3fSmrg   # from the first argument.
64201e04c3fSmrg   operation("borrow", 2),
64301e04c3fSmrg
64401e04c3fSmrg   # Either (vector % vector) or (vector % scalar)
64501e04c3fSmrg   #
64601e04c3fSmrg   # We don't use fmod because it rounds toward zero; GLSL specifies the use
64701e04c3fSmrg   # of floor.
64801e04c3fSmrg   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),
64901e04c3fSmrg
65001e04c3fSmrg   # Binary comparison operators which return a boolean vector.
65101e04c3fSmrg   # The type of both operands must be equal.
65201e04c3fSmrg   operation("less", 2, printable_name="<", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} < {src1}"),
65301e04c3fSmrg   operation("gequal", 2, printable_name=">=", source_types=numeric_types, dest_type=bool_type, c_expression="{src0} >= {src1}"),
65401e04c3fSmrg   operation("equal", 2, printable_name="==", source_types=all_types, dest_type=bool_type, c_expression="{src0} == {src1}"),
65501e04c3fSmrg   operation("nequal", 2, printable_name="!=", source_types=all_types, dest_type=bool_type, c_expression="{src0} != {src1}"),
65601e04c3fSmrg
65701e04c3fSmrg   # Returns single boolean for whether all components of operands[0]
65801e04c3fSmrg   # equal the components of operands[1].
65901e04c3fSmrg   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))),
66001e04c3fSmrg
66101e04c3fSmrg   # Returns single boolean for whether any component of operands[0]
66201e04c3fSmrg   # is not equal to the corresponding component of operands[1].
66301e04c3fSmrg   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))),
66401e04c3fSmrg
66501e04c3fSmrg   # Bit-wise binary operations.
66601e04c3fSmrg   operation("lshift", 2, printable_name="<<", source_types=integer_types, c_expression="{src0} << {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
66701e04c3fSmrg   operation("rshift", 2, printable_name=">>", source_types=integer_types, c_expression="{src0} >> {src1}", flags=frozenset((vector_scalar_operation, mixed_type_operation))),
66801e04c3fSmrg   operation("bit_and", 2, printable_name="&", source_types=integer_types, c_expression="{src0} & {src1}", flags=vector_scalar_operation),
66901e04c3fSmrg   operation("bit_xor", 2, printable_name="^", source_types=integer_types, c_expression="{src0} ^ {src1}", flags=vector_scalar_operation),
67001e04c3fSmrg   operation("bit_or", 2, printable_name="|", source_types=integer_types, c_expression="{src0} | {src1}", flags=vector_scalar_operation),
67101e04c3fSmrg
67201e04c3fSmrg   operation("logic_and", 2, printable_name="&&", source_types=(bool_type,), c_expression="{src0} && {src1}"),
67301e04c3fSmrg   operation("logic_xor", 2, printable_name="^^", source_types=(bool_type,), c_expression="{src0} != {src1}"),
67401e04c3fSmrg   operation("logic_or", 2, printable_name="||", source_types=(bool_type,), c_expression="{src0} || {src1}"),
67501e04c3fSmrg
67601e04c3fSmrg   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),
67701e04c3fSmrg   operation("min", 2, source_types=numeric_types, c_expression="MIN2({src0}, {src1})", flags=vector_scalar_operation),
67801e04c3fSmrg   operation("max", 2, source_types=numeric_types, c_expression="MAX2({src0}, {src1})", flags=vector_scalar_operation),
67901e04c3fSmrg
68001e04c3fSmrg   operation("pow", 2, source_types=(float_type,), c_expression="powf({src0}, {src1})"),
68101e04c3fSmrg
68201e04c3fSmrg   # Load a value the size of a given GLSL type from a uniform block.
68301e04c3fSmrg   #
68401e04c3fSmrg   # operand0 is the ir_constant uniform block index in the linked shader.
68501e04c3fSmrg   # operand1 is a byte offset within the uniform block.
68601e04c3fSmrg   operation("ubo_load", 2),
68701e04c3fSmrg
68801e04c3fSmrg   # Multiplies a number by two to a power, part of ARB_gpu_shader5.
68901e04c3fSmrg   operation("ldexp", 2,
69001e04c3fSmrg             all_signatures=((float_type, (float_type, int_type)),
69101e04c3fSmrg                             (double_type, (double_type, int_type))),
69201e04c3fSmrg             c_expression={'f': "ldexpf_flush_subnormal({src0}, {src1})",
69301e04c3fSmrg                           'd': "ldexp_flush_subnormal({src0}, {src1})"}),
69401e04c3fSmrg
69501e04c3fSmrg   # Extract a scalar from a vector
69601e04c3fSmrg   #
69701e04c3fSmrg   # operand0 is the vector
69801e04c3fSmrg   # operand1 is the index of the field to read from operand0
69901e04c3fSmrg   operation("vector_extract", 2, source_types=all_types, c_expression="anything-except-None"),
70001e04c3fSmrg
70101e04c3fSmrg   # Interpolate fs input at offset
70201e04c3fSmrg   #
70301e04c3fSmrg   # operand0 is the fs input
70401e04c3fSmrg   # operand1 is the offset from the pixel center
70501e04c3fSmrg   operation("interpolate_at_offset", 2),
70601e04c3fSmrg
70701e04c3fSmrg   # Interpolate fs input at sample position
70801e04c3fSmrg   #
70901e04c3fSmrg   # operand0 is the fs input
71001e04c3fSmrg   # operand1 is the sample ID
71101e04c3fSmrg   operation("interpolate_at_sample", 2),
71201e04c3fSmrg
7137ec681f3Smrg   operation("atan2", 2, source_types=(float_type,), c_expression="atan2({src0}, {src1})"),
7147ec681f3Smrg
71501e04c3fSmrg   # Fused floating-point multiply-add, part of ARB_gpu_shader5.
71601e04c3fSmrg   operation("fma", 3, source_types=real_types, c_expression="{src0} * {src1} + {src2}"),
71701e04c3fSmrg
71801e04c3fSmrg   operation("lrp", 3, source_types=real_types, c_expression={'f': "{src0} * (1.0f - {src2}) + ({src1} * {src2})", 'd': "{src0} * (1.0 - {src2}) + ({src1} * {src2})"}),
71901e04c3fSmrg
72001e04c3fSmrg   # Conditional Select
72101e04c3fSmrg   #
72201e04c3fSmrg   # A vector conditional select instruction (like ?:, but operating per-
72301e04c3fSmrg   # component on vectors).
72401e04c3fSmrg   #
72501e04c3fSmrg   # See also lower_instructions_visitor::ldexp_to_arith
72601e04c3fSmrg   operation("csel", 3,
72701e04c3fSmrg             all_signatures=zip(all_types, zip(len(all_types) * (bool_type,), all_types, all_types)),
72801e04c3fSmrg             c_expression="{src0} ? {src1} : {src2}"),
72901e04c3fSmrg
73001e04c3fSmrg   operation("bitfield_extract", 3,
73101e04c3fSmrg             all_signatures=((int_type, (uint_type, int_type, int_type)),
73201e04c3fSmrg                             (int_type, (int_type, int_type, int_type))),
73301e04c3fSmrg             c_expression={'u': "bitfield_extract_uint({src0}, {src1}, {src2})",
73401e04c3fSmrg                           'i': "bitfield_extract_int({src0}, {src1}, {src2})"}),
73501e04c3fSmrg
73601e04c3fSmrg   # Generate a value with one field of a vector changed
73701e04c3fSmrg   #
73801e04c3fSmrg   # operand0 is the vector
73901e04c3fSmrg   # operand1 is the value to write into the vector result
74001e04c3fSmrg   # operand2 is the index in operand0 to be modified
74101e04c3fSmrg   operation("vector_insert", 3, source_types=all_types, c_expression="anything-except-None"),
74201e04c3fSmrg
74301e04c3fSmrg   operation("bitfield_insert", 4,
74401e04c3fSmrg             all_signatures=((uint_type, (uint_type, uint_type, int_type, int_type)),
74501e04c3fSmrg                             (int_type, (int_type, int_type, int_type, int_type))),
74601e04c3fSmrg             c_expression="bitfield_insert({src0}, {src1}, {src2}, {src3})"),
74701e04c3fSmrg
74801e04c3fSmrg   operation("vector", 4, source_types=all_types, c_expression="anything-except-None"),
74901e04c3fSmrg]
75001e04c3fSmrg
75101e04c3fSmrg
75201e04c3fSmrgif __name__ == "__main__":
75301e04c3fSmrg   copyright = """/*
75401e04c3fSmrg * Copyright (C) 2010 Intel Corporation
75501e04c3fSmrg *
75601e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
75701e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
75801e04c3fSmrg * to deal in the Software without restriction, including without limitation
75901e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
76001e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
76101e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
76201e04c3fSmrg *
76301e04c3fSmrg * The above copyright notice and this permission notice (including the next
76401e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
76501e04c3fSmrg * Software.
76601e04c3fSmrg *
76701e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76801e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
76901e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
77001e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77101e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
77201e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
77301e04c3fSmrg * DEALINGS IN THE SOFTWARE.
77401e04c3fSmrg */
77501e04c3fSmrg"""
77601e04c3fSmrg   enum_template = mako.template.Template(copyright + """
77701e04c3fSmrgenum ir_expression_operation {
77801e04c3fSmrg% for item in values:
77901e04c3fSmrg   ${item.get_enum_name()},
78001e04c3fSmrg% endfor
78101e04c3fSmrg
78201e04c3fSmrg   /* Sentinels marking the last of each kind of operation. */
78301e04c3fSmrg% for item in lasts:
78401e04c3fSmrg   ir_last_${("un", "bin", "tri", "quad")[item.num_operands - 1]}op = ${item.get_enum_name()},
78501e04c3fSmrg% endfor
78601e04c3fSmrg   ir_last_opcode = ir_quadop_${lasts[3].name}
78701e04c3fSmrg};""")
78801e04c3fSmrg
78901e04c3fSmrg   strings_template = mako.template.Template(copyright + """
79001e04c3fSmrgconst char *const ir_expression_operation_strings[] = {
79101e04c3fSmrg% for item in values:
79201e04c3fSmrg   "${item.printable_name}",
79301e04c3fSmrg% endfor
79401e04c3fSmrg};
79501e04c3fSmrg
79601e04c3fSmrgconst char *const ir_expression_operation_enum_strings[] = {
79701e04c3fSmrg% for item in values:
79801e04c3fSmrg   "${item.name}",
79901e04c3fSmrg% endfor
80001e04c3fSmrg};""")
80101e04c3fSmrg
80201e04c3fSmrg   constant_template = mako.template.Template("""\
80301e04c3fSmrg   switch (this->operation) {
80401e04c3fSmrg% for op in values:
80501e04c3fSmrg    % if op.c_expression is not None:
80601e04c3fSmrg${op.get_template()}
80701e04c3fSmrg
80801e04c3fSmrg    % endif
80901e04c3fSmrg% endfor
81001e04c3fSmrg   default:
81101e04c3fSmrg      /* FINISHME: Should handle all expression types. */
81201e04c3fSmrg      return NULL;
81301e04c3fSmrg   }
81401e04c3fSmrg""")
81501e04c3fSmrg
81601e04c3fSmrg   if sys.argv[1] == "enum":
81701e04c3fSmrg      lasts = [None, None, None, None]
81801e04c3fSmrg      for item in reversed(ir_expression_operation):
81901e04c3fSmrg         i = item.num_operands - 1
82001e04c3fSmrg         if lasts[i] is None:
82101e04c3fSmrg            lasts[i] = item
82201e04c3fSmrg
82301e04c3fSmrg      print(enum_template.render(values=ir_expression_operation,
82401e04c3fSmrg                                 lasts=lasts))
82501e04c3fSmrg   elif sys.argv[1] == "strings":
82601e04c3fSmrg      print(strings_template.render(values=ir_expression_operation))
82701e04c3fSmrg   elif sys.argv[1] == "constant":
82801e04c3fSmrg      print(constant_template.render(values=ir_expression_operation))
829