ir_constant_expression.cpp revision 29285882676388aacff123e8bdf025904abf8ea9
1/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24/**
25 * \file ir_constant_expression.cpp
26 * Evaluate and process constant valued expressions
27 *
28 * In GLSL, constant valued expressions are used in several places.  These
29 * must be processed and evaluated very early in the compilation process.
30 *
31 *    * Sizes of arrays
32 *    * Initializers for uniforms
33 *    * Initializers for \c const variables
34 */
35
36#include <math.h>
37#include "ir.h"
38#include "ir_visitor.h"
39#include "glsl_types.h"
40
41/**
42 * Visitor class for evaluating constant expressions
43 */
44class ir_constant_visitor : public ir_visitor {
45public:
46   ir_constant_visitor()
47      : value(NULL)
48   {
49      /* empty */
50   }
51
52   virtual ~ir_constant_visitor()
53   {
54      /* empty */
55   }
56
57   /**
58    * \name Visit methods
59    *
60    * As typical for the visitor pattern, there must be one \c visit method for
61    * each concrete subclass of \c ir_instruction.  Virtual base classes within
62    * the hierarchy should not have \c visit methods.
63    */
64   /*@{*/
65   virtual void visit(ir_variable *);
66   virtual void visit(ir_function_signature *);
67   virtual void visit(ir_function *);
68   virtual void visit(ir_expression *);
69   virtual void visit(ir_texture *);
70   virtual void visit(ir_swizzle *);
71   virtual void visit(ir_dereference_variable *);
72   virtual void visit(ir_dereference_array *);
73   virtual void visit(ir_dereference_record *);
74   virtual void visit(ir_assignment *);
75   virtual void visit(ir_constant *);
76   virtual void visit(ir_call *);
77   virtual void visit(ir_return *);
78   virtual void visit(ir_if *);
79   virtual void visit(ir_loop *);
80   virtual void visit(ir_loop_jump *);
81   /*@}*/
82
83   /**
84    * Value of the constant expression.
85    *
86    * \note
87    * This field will be \c NULL if the expression is not constant valued.
88    */
89   /* FINIHSME: This cannot hold values for constant arrays or structures. */
90   ir_constant *value;
91};
92
93
94ir_constant *
95ir_instruction::constant_expression_value()
96{
97   ir_constant_visitor visitor;
98
99   this->accept(& visitor);
100   return visitor.value;
101}
102
103
104void
105ir_constant_visitor::visit(ir_variable *ir)
106{
107   (void) ir;
108   value = NULL;
109}
110
111
112void
113ir_constant_visitor::visit(ir_function_signature *ir)
114{
115   (void) ir;
116   value = NULL;
117}
118
119
120void
121ir_constant_visitor::visit(ir_function *ir)
122{
123   (void) ir;
124   value = NULL;
125}
126
127void
128ir_constant_visitor::visit(ir_expression *ir)
129{
130   value = NULL;
131   ir_constant *op[2];
132   unsigned int operand, c;
133   ir_constant_data data;
134
135   for (operand = 0; operand < ir->get_num_operands(); operand++) {
136      op[operand] = ir->operands[operand]->constant_expression_value();
137      if (!op[operand])
138	 return;
139   }
140
141   switch (ir->operation) {
142   case ir_unop_logic_not:
143      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
144      for (c = 0; c < ir->operands[0]->type->components(); c++)
145	 data.b[c] = !op[0]->value.b[c];
146      break;
147
148   case ir_unop_f2i:
149      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
150      for (c = 0; c < ir->operands[0]->type->components(); c++) {
151	 data.i[c] = op[0]->value.f[c];
152      }
153      break;
154   case ir_unop_i2f:
155      assert(op[0]->type->base_type == GLSL_TYPE_UINT ||
156	     op[0]->type->base_type == GLSL_TYPE_INT);
157      for (c = 0; c < ir->operands[0]->type->components(); c++) {
158	 if (op[0]->type->base_type == GLSL_TYPE_INT)
159	    data.f[c] = op[0]->value.i[c];
160	 else
161	    data.f[c] = op[0]->value.u[c];
162      }
163      break;
164   case ir_unop_b2f:
165      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
166      for (c = 0; c < ir->operands[0]->type->components(); c++) {
167	 data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
168      }
169      break;
170   case ir_unop_f2b:
171      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
172      for (c = 0; c < ir->operands[0]->type->components(); c++) {
173	 data.b[c] = bool(op[0]->value.f[c]);
174      }
175      break;
176   case ir_unop_b2i:
177      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
178      for (c = 0; c < ir->operands[0]->type->components(); c++) {
179	 data.u[c] = op[0]->value.b[c] ? 1 : 0;
180      }
181      break;
182   case ir_unop_i2b:
183      assert(op[0]->type->is_integer());
184      for (c = 0; c < ir->operands[0]->type->components(); c++) {
185	 data.b[c] = bool(op[0]->value.u[c]);
186      }
187      break;
188
189   case ir_unop_neg:
190      for (c = 0; c < ir->operands[0]->type->components(); c++) {
191	 switch (ir->type->base_type) {
192	 case GLSL_TYPE_UINT:
193	    data.u[c] = -op[0]->value.u[c];
194	    break;
195	 case GLSL_TYPE_INT:
196	    data.i[c] = -op[0]->value.i[c];
197	    break;
198	 case GLSL_TYPE_FLOAT:
199	    data.f[c] = -op[0]->value.f[c];
200	    break;
201	 default:
202	    assert(0);
203	 }
204      }
205      break;
206
207   case ir_unop_abs:
208      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
209      for (c = 0; c < ir->operands[0]->type->components(); c++) {
210	 switch (ir->type->base_type) {
211	 case GLSL_TYPE_UINT:
212	    data.u[c] = op[0]->value.u[c];
213	    break;
214	 case GLSL_TYPE_INT:
215	    data.i[c] = op[0]->value.i[c];
216	    if (data.i[c] < 0)
217	       data.i[c] = -data.i[c];
218	    break;
219	 case GLSL_TYPE_FLOAT:
220	    data.f[c] = fabs(op[0]->value.f[c]);
221	    break;
222	 default:
223	    assert(0);
224	 }
225      }
226      break;
227
228   case ir_unop_rcp:
229      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
230      for (c = 0; c < ir->operands[0]->type->components(); c++) {
231	 switch (ir->type->base_type) {
232	 case GLSL_TYPE_UINT:
233	    if (op[0]->value.u[c] != 0.0)
234	       data.u[c] = 1 / op[0]->value.u[c];
235	    break;
236	 case GLSL_TYPE_INT:
237	    if (op[0]->value.i[c] != 0.0)
238	       data.i[c] = 1 / op[0]->value.i[c];
239	    break;
240	 case GLSL_TYPE_FLOAT:
241	    if (op[0]->value.f[c] != 0.0)
242	       data.f[c] = 1.0 / op[0]->value.f[c];
243	    break;
244	 default:
245	    assert(0);
246	 }
247      }
248      break;
249
250   case ir_unop_rsq:
251      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
252      for (c = 0; c < ir->operands[0]->type->components(); c++) {
253	 data.f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
254      }
255      break;
256
257   case ir_unop_sqrt:
258      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
259      for (c = 0; c < ir->operands[0]->type->components(); c++) {
260	 data.f[c] = sqrtf(op[0]->value.f[c]);
261      }
262      break;
263
264   case ir_unop_exp:
265      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
266      for (c = 0; c < ir->operands[0]->type->components(); c++) {
267	 data.f[c] = expf(op[0]->value.f[c]);
268      }
269      break;
270
271   case ir_unop_log:
272      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
273      for (c = 0; c < ir->operands[0]->type->components(); c++) {
274	 data.f[c] = logf(op[0]->value.f[c]);
275      }
276      break;
277
278   case ir_unop_dFdx:
279   case ir_unop_dFdy:
280      assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
281      for (c = 0; c < ir->operands[0]->type->components(); c++) {
282	 data.f[c] = 0.0;
283      }
284      break;
285
286   case ir_binop_add:
287      if (ir->operands[0]->type == ir->operands[1]->type) {
288	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
289	    switch (ir->operands[0]->type->base_type) {
290	    case GLSL_TYPE_UINT:
291	       data.u[c] = op[0]->value.u[c] + op[1]->value.u[c];
292	       break;
293	    case GLSL_TYPE_INT:
294	       data.i[c] = op[0]->value.i[c] + op[1]->value.i[c];
295	       break;
296	    case GLSL_TYPE_FLOAT:
297	       data.f[c] = op[0]->value.f[c] + op[1]->value.f[c];
298	       break;
299	    default:
300	       assert(0);
301	    }
302	 }
303      } else
304	 /* FINISHME: Support operations with non-equal types. */
305	 return;
306
307      break;
308   case ir_binop_sub:
309      if (ir->operands[0]->type == ir->operands[1]->type) {
310	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
311	    switch (ir->operands[0]->type->base_type) {
312	    case GLSL_TYPE_UINT:
313	       data.u[c] = op[0]->value.u[c] - op[1]->value.u[c];
314	       break;
315	    case GLSL_TYPE_INT:
316	       data.i[c] = op[0]->value.i[c] - op[1]->value.i[c];
317	       break;
318	    case GLSL_TYPE_FLOAT:
319	       data.f[c] = op[0]->value.f[c] - op[1]->value.f[c];
320	       break;
321	    default:
322	       assert(0);
323	    }
324	 }
325      } else
326	 /* FINISHME: Support operations with non-equal types. */
327	 return;
328
329      break;
330   case ir_binop_mul:
331      if (ir->operands[0]->type == ir->operands[1]->type &&
332	  !ir->operands[0]->type->is_matrix()) {
333	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
334	    switch (ir->operands[0]->type->base_type) {
335	    case GLSL_TYPE_UINT:
336	       data.u[c] = op[0]->value.u[c] * op[1]->value.u[c];
337	       break;
338	    case GLSL_TYPE_INT:
339	       data.i[c] = op[0]->value.i[c] * op[1]->value.i[c];
340	       break;
341	    case GLSL_TYPE_FLOAT:
342	       data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
343	       break;
344	    default:
345	       assert(0);
346	    }
347	 }
348      } else
349	 /* FINISHME: Support operations with non-equal types. */
350	 return;
351
352      break;
353   case ir_binop_div:
354      if (ir->operands[0]->type == ir->operands[1]->type) {
355	 for (c = 0; c < ir->operands[0]->type->components(); c++) {
356	    switch (ir->operands[0]->type->base_type) {
357	    case GLSL_TYPE_UINT:
358	       data.u[c] = op[0]->value.u[c] / op[1]->value.u[c];
359	       break;
360	    case GLSL_TYPE_INT:
361	       data.i[c] = op[0]->value.i[c] / op[1]->value.i[c];
362	       break;
363	    case GLSL_TYPE_FLOAT:
364	       data.f[c] = op[0]->value.f[c] / op[1]->value.f[c];
365	       break;
366	    default:
367	       assert(0);
368	    }
369	 }
370      } else
371	 /* FINISHME: Support operations with non-equal types. */
372	 return;
373
374      break;
375   case ir_binop_logic_and:
376      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
377      for (c = 0; c < ir->operands[0]->type->components(); c++)
378	 data.b[c] = op[0]->value.b[c] && op[1]->value.b[c];
379      break;
380   case ir_binop_logic_xor:
381      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
382      for (c = 0; c < ir->operands[0]->type->components(); c++)
383	 data.b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
384      break;
385   case ir_binop_logic_or:
386      assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
387      for (c = 0; c < ir->operands[0]->type->components(); c++)
388	 data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
389      break;
390
391   case ir_binop_less:
392      switch (ir->operands[0]->type->base_type) {
393      case GLSL_TYPE_UINT:
394	 data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
395	 break;
396      case GLSL_TYPE_INT:
397	 data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
398	 break;
399      case GLSL_TYPE_FLOAT:
400	 data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
401	 break;
402      default:
403	 assert(0);
404      }
405      break;
406   case ir_binop_greater:
407      switch (ir->operands[0]->type->base_type) {
408      case GLSL_TYPE_UINT:
409	 data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
410	 break;
411      case GLSL_TYPE_INT:
412	 data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
413	 break;
414      case GLSL_TYPE_FLOAT:
415	 data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
416	 break;
417      default:
418	 assert(0);
419      }
420      break;
421   case ir_binop_lequal:
422      switch (ir->operands[0]->type->base_type) {
423      case GLSL_TYPE_UINT:
424	 data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
425	 break;
426      case GLSL_TYPE_INT:
427	 data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
428	 break;
429      case GLSL_TYPE_FLOAT:
430	 data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
431	 break;
432      default:
433	 assert(0);
434      }
435      break;
436   case ir_binop_gequal:
437      switch (ir->operands[0]->type->base_type) {
438      case GLSL_TYPE_UINT:
439	 data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
440	 break;
441      case GLSL_TYPE_INT:
442	 data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
443	 break;
444      case GLSL_TYPE_FLOAT:
445	 data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
446	 break;
447      default:
448	 assert(0);
449      }
450      break;
451
452   case ir_binop_equal:
453      data.b[0] = true;
454      for (c = 0; c < ir->operands[0]->type->components(); c++) {
455	 switch (ir->operands[0]->type->base_type) {
456	 case GLSL_TYPE_UINT:
457	    data.b[0] = data.b[0] && op[0]->value.u[c] == op[1]->value.u[c];
458	    break;
459	 case GLSL_TYPE_INT:
460	    data.b[0] = data.b[0] && op[0]->value.i[c] == op[1]->value.i[c];
461	    break;
462	 case GLSL_TYPE_FLOAT:
463	    data.b[0] = data.b[0] && op[0]->value.f[c] == op[1]->value.f[c];
464	    break;
465	 case GLSL_TYPE_BOOL:
466	    data.b[0] = data.b[0] && op[0]->value.b[c] == op[1]->value.b[c];
467	    break;
468	 default:
469	    assert(0);
470	 }
471      }
472      break;
473   case ir_binop_nequal:
474      data.b[0] = false;
475      for (c = 0; c < ir->operands[0]->type->components(); c++) {
476	 switch (ir->operands[0]->type->base_type) {
477	 case GLSL_TYPE_UINT:
478	    data.b[0] = data.b[0] || op[0]->value.u[c] != op[1]->value.u[c];
479	    break;
480	 case GLSL_TYPE_INT:
481	    data.b[0] = data.b[0] || op[0]->value.i[c] != op[1]->value.i[c];
482	    break;
483	 case GLSL_TYPE_FLOAT:
484	    data.b[0] = data.b[0] || op[0]->value.f[c] != op[1]->value.f[c];
485	    break;
486	 case GLSL_TYPE_BOOL:
487	    data.b[0] = data.b[0] || op[0]->value.b[c] != op[1]->value.b[c];
488	    break;
489	 default:
490	    assert(0);
491	 }
492      }
493      break;
494
495   default:
496      /* FINISHME: Should handle all expression types. */
497      return;
498   }
499
500   void *ctx = talloc_parent(ir);
501   this->value = new(ctx) ir_constant(ir->type, &data);
502}
503
504
505void
506ir_constant_visitor::visit(ir_texture *ir)
507{
508   // FINISHME: Do stuff with texture lookups
509   (void) ir;
510   value = NULL;
511}
512
513
514void
515ir_constant_visitor::visit(ir_swizzle *ir)
516{
517   ir_constant *v = ir->val->constant_expression_value();
518
519   this->value = NULL;
520
521   if (v != NULL) {
522      ir_constant_data data;
523
524      const unsigned swiz_idx[4] = {
525	 ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w
526      };
527
528      for (unsigned i = 0; i < ir->mask.num_components; i++) {
529	 switch (v->type->base_type) {
530	 case GLSL_TYPE_UINT:
531	 case GLSL_TYPE_INT:   data.u[i] = v->value.u[swiz_idx[i]]; break;
532	 case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
533	 case GLSL_TYPE_BOOL:  data.b[i] = v->value.b[swiz_idx[i]]; break;
534	 default:              assert(!"Should not get here."); break;
535	 }
536      }
537
538      void *ctx = talloc_parent(ir);
539      this->value = new(ctx) ir_constant(ir->type, &data);
540   }
541}
542
543
544void
545ir_constant_visitor::visit(ir_dereference_variable *ir)
546{
547   value = NULL;
548
549   ir_variable *var = ir->variable_referenced();
550   if (var && var->constant_value)
551      value = (ir_constant *)var->constant_value->clone(NULL);
552}
553
554
555void
556ir_constant_visitor::visit(ir_dereference_array *ir)
557{
558   void *ctx = talloc_parent(ir);
559   ir_constant *array = ir->array->constant_expression_value();
560   ir_constant *idx = ir->array_index->constant_expression_value();
561
562   this->value = NULL;
563
564   if ((array != NULL) && (idx != NULL)) {
565      if (array->type->is_matrix()) {
566	 /* Array access of a matrix results in a vector.
567	  */
568	 const unsigned column = idx->value.u[0];
569
570	 const glsl_type *const column_type = array->type->column_type();
571
572	 /* Offset in the constant matrix to the first element of the column
573	  * to be extracted.
574	  */
575	 const unsigned mat_idx = column * column_type->vector_elements;
576
577	 ir_constant_data data;
578
579	 switch (column_type->base_type) {
580	 case GLSL_TYPE_UINT:
581	 case GLSL_TYPE_INT:
582	    for (unsigned i = 0; i < column_type->vector_elements; i++)
583	       data.u[i] = array->value.u[mat_idx + i];
584
585	    break;
586
587	 case GLSL_TYPE_FLOAT:
588	    for (unsigned i = 0; i < column_type->vector_elements; i++)
589	       data.f[i] = array->value.f[mat_idx + i];
590
591	    break;
592
593	 default:
594	    assert(!"Should not get here.");
595	    break;
596	 }
597
598	 this->value = new(ctx) ir_constant(column_type, &data);
599      } else if (array->type->is_vector()) {
600	 const unsigned component = idx->value.u[0];
601
602	 this->value = new(ctx) ir_constant(array, component);
603      } else {
604	 /* FINISHME: Handle access of constant arrays. */
605      }
606   }
607}
608
609
610void
611ir_constant_visitor::visit(ir_dereference_record *ir)
612{
613   ir_constant *v = ir->record->constant_expression_value();
614
615   this->value = (v != NULL) ? v->get_record_field(ir->field) : NULL;
616}
617
618
619void
620ir_constant_visitor::visit(ir_assignment *ir)
621{
622   (void) ir;
623   value = NULL;
624}
625
626
627void
628ir_constant_visitor::visit(ir_constant *ir)
629{
630   value = ir;
631}
632
633
634void
635ir_constant_visitor::visit(ir_call *ir)
636{
637   (void) ir;
638   value = NULL;
639}
640
641
642void
643ir_constant_visitor::visit(ir_return *ir)
644{
645   (void) ir;
646   value = NULL;
647}
648
649
650void
651ir_constant_visitor::visit(ir_if *ir)
652{
653   (void) ir;
654   value = NULL;
655}
656
657
658void
659ir_constant_visitor::visit(ir_loop *ir)
660{
661   (void) ir;
662   value = NULL;
663}
664
665
666void
667ir_constant_visitor::visit(ir_loop_jump *ir)
668{
669   (void) ir;
670   value = NULL;
671}
672