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