ir_constant_expression: Initialize all components of constant data to 0.
[mesa.git] / src / glsl / ir_constant_expression.cpp
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 */
44 class ir_constant_visitor : public ir_visitor {
45 public:
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_discard *);
79 virtual void visit(ir_if *);
80 virtual void visit(ir_loop *);
81 virtual void visit(ir_loop_jump *);
82 /*@}*/
83
84 /**
85 * Value of the constant expression.
86 *
87 * \note
88 * This field will be \c NULL if the expression is not constant valued.
89 */
90 /* FINIHSME: This cannot hold values for constant arrays or structures. */
91 ir_constant *value;
92 };
93
94
95 ir_constant *
96 ir_instruction::constant_expression_value()
97 {
98 ir_constant_visitor visitor;
99
100 this->accept(& visitor);
101 return visitor.value;
102 }
103
104
105 void
106 ir_constant_visitor::visit(ir_variable *ir)
107 {
108 (void) ir;
109 value = NULL;
110 }
111
112
113 void
114 ir_constant_visitor::visit(ir_function_signature *ir)
115 {
116 (void) ir;
117 value = NULL;
118 }
119
120
121 void
122 ir_constant_visitor::visit(ir_function *ir)
123 {
124 (void) ir;
125 value = NULL;
126 }
127
128 void
129 ir_constant_visitor::visit(ir_expression *ir)
130 {
131 value = NULL;
132 ir_constant *op[2];
133 unsigned int operand, c;
134 ir_constant_data data;
135
136 memset(&data, 0, sizeof(data));
137
138 for (operand = 0; operand < ir->get_num_operands(); operand++) {
139 op[operand] = ir->operands[operand]->constant_expression_value();
140 if (!op[operand])
141 return;
142 }
143
144 switch (ir->operation) {
145 case ir_unop_logic_not:
146 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
147 for (c = 0; c < ir->operands[0]->type->components(); c++)
148 data.b[c] = !op[0]->value.b[c];
149 break;
150
151 case ir_unop_f2i:
152 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
153 for (c = 0; c < ir->operands[0]->type->components(); c++) {
154 data.i[c] = op[0]->value.f[c];
155 }
156 break;
157 case ir_unop_i2f:
158 assert(op[0]->type->base_type == GLSL_TYPE_UINT ||
159 op[0]->type->base_type == GLSL_TYPE_INT);
160 for (c = 0; c < ir->operands[0]->type->components(); c++) {
161 if (op[0]->type->base_type == GLSL_TYPE_INT)
162 data.f[c] = op[0]->value.i[c];
163 else
164 data.f[c] = op[0]->value.u[c];
165 }
166 break;
167 case ir_unop_b2f:
168 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
169 for (c = 0; c < ir->operands[0]->type->components(); c++) {
170 data.f[c] = op[0]->value.b[c] ? 1.0 : 0.0;
171 }
172 break;
173 case ir_unop_f2b:
174 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
175 for (c = 0; c < ir->operands[0]->type->components(); c++) {
176 data.b[c] = bool(op[0]->value.f[c]);
177 }
178 break;
179 case ir_unop_b2i:
180 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
181 for (c = 0; c < ir->operands[0]->type->components(); c++) {
182 data.u[c] = op[0]->value.b[c] ? 1 : 0;
183 }
184 break;
185 case ir_unop_i2b:
186 assert(op[0]->type->is_integer());
187 for (c = 0; c < ir->operands[0]->type->components(); c++) {
188 data.b[c] = bool(op[0]->value.u[c]);
189 }
190 break;
191
192 case ir_unop_fract:
193 for (c = 0; c < ir->operands[0]->type->components(); c++) {
194 switch (ir->type->base_type) {
195 case GLSL_TYPE_UINT:
196 data.u[c] = 0;
197 break;
198 case GLSL_TYPE_INT:
199 data.i[c] = 0;
200 break;
201 case GLSL_TYPE_FLOAT:
202 data.f[c] = op[0]->value.f[c] - floor(op[0]->value.f[c]);
203 break;
204 default:
205 assert(0);
206 }
207 }
208 break;
209
210 case ir_unop_neg:
211 for (c = 0; c < ir->operands[0]->type->components(); c++) {
212 switch (ir->type->base_type) {
213 case GLSL_TYPE_UINT:
214 data.u[c] = -op[0]->value.u[c];
215 break;
216 case GLSL_TYPE_INT:
217 data.i[c] = -op[0]->value.i[c];
218 break;
219 case GLSL_TYPE_FLOAT:
220 data.f[c] = -op[0]->value.f[c];
221 break;
222 default:
223 assert(0);
224 }
225 }
226 break;
227
228 case ir_unop_abs:
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 data.u[c] = op[0]->value.u[c];
234 break;
235 case GLSL_TYPE_INT:
236 data.i[c] = op[0]->value.i[c];
237 if (data.i[c] < 0)
238 data.i[c] = -data.i[c];
239 break;
240 case GLSL_TYPE_FLOAT:
241 data.f[c] = fabs(op[0]->value.f[c]);
242 break;
243 default:
244 assert(0);
245 }
246 }
247 break;
248
249 case ir_unop_rcp:
250 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
251 for (c = 0; c < ir->operands[0]->type->components(); c++) {
252 switch (ir->type->base_type) {
253 case GLSL_TYPE_UINT:
254 if (op[0]->value.u[c] != 0.0)
255 data.u[c] = 1 / op[0]->value.u[c];
256 break;
257 case GLSL_TYPE_INT:
258 if (op[0]->value.i[c] != 0.0)
259 data.i[c] = 1 / op[0]->value.i[c];
260 break;
261 case GLSL_TYPE_FLOAT:
262 if (op[0]->value.f[c] != 0.0)
263 data.f[c] = 1.0 / op[0]->value.f[c];
264 break;
265 default:
266 assert(0);
267 }
268 }
269 break;
270
271 case ir_unop_rsq:
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] = 1.0 / sqrtf(op[0]->value.f[c]);
275 }
276 break;
277
278 case ir_unop_sqrt:
279 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
280 for (c = 0; c < ir->operands[0]->type->components(); c++) {
281 data.f[c] = sqrtf(op[0]->value.f[c]);
282 }
283 break;
284
285 case ir_unop_exp:
286 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
287 for (c = 0; c < ir->operands[0]->type->components(); c++) {
288 data.f[c] = expf(op[0]->value.f[c]);
289 }
290 break;
291
292 case ir_unop_log:
293 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
294 for (c = 0; c < ir->operands[0]->type->components(); c++) {
295 data.f[c] = logf(op[0]->value.f[c]);
296 }
297 break;
298
299 case ir_unop_dFdx:
300 case ir_unop_dFdy:
301 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
302 for (c = 0; c < ir->operands[0]->type->components(); c++) {
303 data.f[c] = 0.0;
304 }
305 break;
306
307 case ir_binop_add:
308 if (ir->operands[0]->type == ir->operands[1]->type) {
309 for (c = 0; c < ir->operands[0]->type->components(); c++) {
310 switch (ir->operands[0]->type->base_type) {
311 case GLSL_TYPE_UINT:
312 data.u[c] = op[0]->value.u[c] + op[1]->value.u[c];
313 break;
314 case GLSL_TYPE_INT:
315 data.i[c] = op[0]->value.i[c] + op[1]->value.i[c];
316 break;
317 case GLSL_TYPE_FLOAT:
318 data.f[c] = op[0]->value.f[c] + op[1]->value.f[c];
319 break;
320 default:
321 assert(0);
322 }
323 }
324 } else
325 /* FINISHME: Support operations with non-equal types. */
326 return;
327
328 break;
329 case ir_binop_sub:
330 if (ir->operands[0]->type == ir->operands[1]->type) {
331 for (c = 0; c < ir->operands[0]->type->components(); c++) {
332 switch (ir->operands[0]->type->base_type) {
333 case GLSL_TYPE_UINT:
334 data.u[c] = op[0]->value.u[c] - op[1]->value.u[c];
335 break;
336 case GLSL_TYPE_INT:
337 data.i[c] = op[0]->value.i[c] - op[1]->value.i[c];
338 break;
339 case GLSL_TYPE_FLOAT:
340 data.f[c] = op[0]->value.f[c] - op[1]->value.f[c];
341 break;
342 default:
343 assert(0);
344 }
345 }
346 } else
347 /* FINISHME: Support operations with non-equal types. */
348 return;
349
350 break;
351 case ir_binop_mul:
352 if (ir->operands[0]->type == ir->operands[1]->type &&
353 !ir->operands[0]->type->is_matrix()) {
354 for (c = 0; c < ir->operands[0]->type->components(); c++) {
355 switch (ir->operands[0]->type->base_type) {
356 case GLSL_TYPE_UINT:
357 data.u[c] = op[0]->value.u[c] * op[1]->value.u[c];
358 break;
359 case GLSL_TYPE_INT:
360 data.i[c] = op[0]->value.i[c] * op[1]->value.i[c];
361 break;
362 case GLSL_TYPE_FLOAT:
363 data.f[c] = op[0]->value.f[c] * op[1]->value.f[c];
364 break;
365 default:
366 assert(0);
367 }
368 }
369 } else
370 /* FINISHME: Support operations with non-equal types. */
371 return;
372
373 break;
374 case ir_binop_div:
375 if (ir->operands[0]->type == ir->operands[1]->type) {
376 for (c = 0; c < ir->operands[0]->type->components(); c++) {
377 switch (ir->operands[0]->type->base_type) {
378 case GLSL_TYPE_UINT:
379 data.u[c] = op[0]->value.u[c] / op[1]->value.u[c];
380 break;
381 case GLSL_TYPE_INT:
382 data.i[c] = op[0]->value.i[c] / op[1]->value.i[c];
383 break;
384 case GLSL_TYPE_FLOAT:
385 data.f[c] = op[0]->value.f[c] / op[1]->value.f[c];
386 break;
387 default:
388 assert(0);
389 }
390 }
391 } else
392 /* FINISHME: Support operations with non-equal types. */
393 return;
394
395 break;
396 case ir_binop_logic_and:
397 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
398 for (c = 0; c < ir->operands[0]->type->components(); c++)
399 data.b[c] = op[0]->value.b[c] && op[1]->value.b[c];
400 break;
401 case ir_binop_logic_xor:
402 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
403 for (c = 0; c < ir->operands[0]->type->components(); c++)
404 data.b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
405 break;
406 case ir_binop_logic_or:
407 assert(op[0]->type->base_type == GLSL_TYPE_BOOL);
408 for (c = 0; c < ir->operands[0]->type->components(); c++)
409 data.b[c] = op[0]->value.b[c] || op[1]->value.b[c];
410 break;
411
412 case ir_binop_less:
413 switch (ir->operands[0]->type->base_type) {
414 case GLSL_TYPE_UINT:
415 data.b[0] = op[0]->value.u[0] < op[1]->value.u[0];
416 break;
417 case GLSL_TYPE_INT:
418 data.b[0] = op[0]->value.i[0] < op[1]->value.i[0];
419 break;
420 case GLSL_TYPE_FLOAT:
421 data.b[0] = op[0]->value.f[0] < op[1]->value.f[0];
422 break;
423 default:
424 assert(0);
425 }
426 break;
427 case ir_binop_greater:
428 switch (ir->operands[0]->type->base_type) {
429 case GLSL_TYPE_UINT:
430 data.b[0] = op[0]->value.u[0] > op[1]->value.u[0];
431 break;
432 case GLSL_TYPE_INT:
433 data.b[0] = op[0]->value.i[0] > op[1]->value.i[0];
434 break;
435 case GLSL_TYPE_FLOAT:
436 data.b[0] = op[0]->value.f[0] > op[1]->value.f[0];
437 break;
438 default:
439 assert(0);
440 }
441 break;
442 case ir_binop_lequal:
443 switch (ir->operands[0]->type->base_type) {
444 case GLSL_TYPE_UINT:
445 data.b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
446 break;
447 case GLSL_TYPE_INT:
448 data.b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
449 break;
450 case GLSL_TYPE_FLOAT:
451 data.b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
452 break;
453 default:
454 assert(0);
455 }
456 break;
457 case ir_binop_gequal:
458 switch (ir->operands[0]->type->base_type) {
459 case GLSL_TYPE_UINT:
460 data.b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
461 break;
462 case GLSL_TYPE_INT:
463 data.b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
464 break;
465 case GLSL_TYPE_FLOAT:
466 data.b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
467 break;
468 default:
469 assert(0);
470 }
471 break;
472
473 case ir_binop_equal:
474 data.b[0] = true;
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 case ir_binop_nequal:
495 data.b[0] = false;
496 for (c = 0; c < ir->operands[0]->type->components(); c++) {
497 switch (ir->operands[0]->type->base_type) {
498 case GLSL_TYPE_UINT:
499 data.b[0] = data.b[0] || op[0]->value.u[c] != op[1]->value.u[c];
500 break;
501 case GLSL_TYPE_INT:
502 data.b[0] = data.b[0] || op[0]->value.i[c] != op[1]->value.i[c];
503 break;
504 case GLSL_TYPE_FLOAT:
505 data.b[0] = data.b[0] || op[0]->value.f[c] != op[1]->value.f[c];
506 break;
507 case GLSL_TYPE_BOOL:
508 data.b[0] = data.b[0] || op[0]->value.b[c] != op[1]->value.b[c];
509 break;
510 default:
511 assert(0);
512 }
513 }
514 break;
515
516 default:
517 /* FINISHME: Should handle all expression types. */
518 return;
519 }
520
521 void *ctx = talloc_parent(ir);
522 this->value = new(ctx) ir_constant(ir->type, &data);
523 }
524
525
526 void
527 ir_constant_visitor::visit(ir_texture *ir)
528 {
529 // FINISHME: Do stuff with texture lookups
530 (void) ir;
531 value = NULL;
532 }
533
534
535 void
536 ir_constant_visitor::visit(ir_swizzle *ir)
537 {
538 ir_constant *v = ir->val->constant_expression_value();
539
540 this->value = NULL;
541
542 if (v != NULL) {
543 ir_constant_data data;
544
545 const unsigned swiz_idx[4] = {
546 ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w
547 };
548
549 for (unsigned i = 0; i < ir->mask.num_components; i++) {
550 switch (v->type->base_type) {
551 case GLSL_TYPE_UINT:
552 case GLSL_TYPE_INT: data.u[i] = v->value.u[swiz_idx[i]]; break;
553 case GLSL_TYPE_FLOAT: data.f[i] = v->value.f[swiz_idx[i]]; break;
554 case GLSL_TYPE_BOOL: data.b[i] = v->value.b[swiz_idx[i]]; break;
555 default: assert(!"Should not get here."); break;
556 }
557 }
558
559 void *ctx = talloc_parent(ir);
560 this->value = new(ctx) ir_constant(ir->type, &data);
561 }
562 }
563
564
565 void
566 ir_constant_visitor::visit(ir_dereference_variable *ir)
567 {
568 value = NULL;
569
570 ir_variable *var = ir->variable_referenced();
571 if (var && var->constant_value)
572 value = (ir_constant *)var->constant_value->clone(NULL);
573 }
574
575
576 void
577 ir_constant_visitor::visit(ir_dereference_array *ir)
578 {
579 void *ctx = talloc_parent(ir);
580 ir_constant *array = ir->array->constant_expression_value();
581 ir_constant *idx = ir->array_index->constant_expression_value();
582
583 this->value = NULL;
584
585 if ((array != NULL) && (idx != NULL)) {
586 if (array->type->is_matrix()) {
587 /* Array access of a matrix results in a vector.
588 */
589 const unsigned column = idx->value.u[0];
590
591 const glsl_type *const column_type = array->type->column_type();
592
593 /* Offset in the constant matrix to the first element of the column
594 * to be extracted.
595 */
596 const unsigned mat_idx = column * column_type->vector_elements;
597
598 ir_constant_data data;
599
600 switch (column_type->base_type) {
601 case GLSL_TYPE_UINT:
602 case GLSL_TYPE_INT:
603 for (unsigned i = 0; i < column_type->vector_elements; i++)
604 data.u[i] = array->value.u[mat_idx + i];
605
606 break;
607
608 case GLSL_TYPE_FLOAT:
609 for (unsigned i = 0; i < column_type->vector_elements; i++)
610 data.f[i] = array->value.f[mat_idx + i];
611
612 break;
613
614 default:
615 assert(!"Should not get here.");
616 break;
617 }
618
619 this->value = new(ctx) ir_constant(column_type, &data);
620 } else if (array->type->is_vector()) {
621 const unsigned component = idx->value.u[0];
622
623 this->value = new(ctx) ir_constant(array, component);
624 } else {
625 /* FINISHME: Handle access of constant arrays. */
626 }
627 }
628 }
629
630
631 void
632 ir_constant_visitor::visit(ir_dereference_record *ir)
633 {
634 ir_constant *v = ir->record->constant_expression_value();
635
636 this->value = (v != NULL) ? v->get_record_field(ir->field) : NULL;
637 }
638
639
640 void
641 ir_constant_visitor::visit(ir_assignment *ir)
642 {
643 (void) ir;
644 value = NULL;
645 }
646
647
648 void
649 ir_constant_visitor::visit(ir_constant *ir)
650 {
651 value = ir;
652 }
653
654
655 void
656 ir_constant_visitor::visit(ir_call *ir)
657 {
658 (void) ir;
659 value = NULL;
660 }
661
662
663 void
664 ir_constant_visitor::visit(ir_return *ir)
665 {
666 (void) ir;
667 value = NULL;
668 }
669
670
671 void
672 ir_constant_visitor::visit(ir_discard *ir)
673 {
674 (void) ir;
675 value = NULL;
676 }
677
678
679 void
680 ir_constant_visitor::visit(ir_if *ir)
681 {
682 (void) ir;
683 value = NULL;
684 }
685
686
687 void
688 ir_constant_visitor::visit(ir_loop *ir)
689 {
690 (void) ir;
691 value = NULL;
692 }
693
694
695 void
696 ir_constant_visitor::visit(ir_loop_jump *ir)
697 {
698 (void) ir;
699 value = NULL;
700 }