2 * Copyright © 2010 Intel Corporation
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:
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
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.
25 * \file ir_constant_expression.cpp
26 * Evaluate and process constant valued expressions
28 * In GLSL, constant valued expressions are used in several places. These
29 * must be processed and evaluated very early in the compilation process.
32 * * Initializers for uniforms
33 * * Initializers for \c const variables
38 #include "ir_visitor.h"
39 #include "glsl_types.h"
42 * Visitor class for evaluating constant expressions
44 class ir_constant_visitor
: public ir_visitor
{
52 virtual ~ir_constant_visitor()
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.
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
*);
84 * Value of the constant expression.
87 * This field will be \c NULL if the expression is not constant valued.
89 /* FINIHSME: This cannot hold values for constant arrays or structures. */
95 ir_instruction::constant_expression_value()
97 ir_constant_visitor visitor
;
99 this->accept(& visitor
);
100 return visitor
.value
;
105 ir_constant_visitor::visit(ir_variable
*ir
)
113 ir_constant_visitor::visit(ir_function_signature
*ir
)
121 ir_constant_visitor::visit(ir_function
*ir
)
128 ir_constant_visitor::visit(ir_expression
*ir
)
132 unsigned int operand
, c
;
133 ir_constant_data data
;
135 for (operand
= 0; operand
< ir
->get_num_operands(); operand
++) {
136 op
[operand
] = ir
->operands
[operand
]->constant_expression_value();
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
];
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
];
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
];
161 data
.f
[c
] = op
[0]->value
.u
[c
];
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;
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
]);
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;
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
]);
190 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
191 switch (ir
->type
->base_type
) {
193 data
.u
[c
] = -op
[0]->value
.u
[c
];
196 data
.i
[c
] = -op
[0]->value
.i
[c
];
198 case GLSL_TYPE_FLOAT
:
199 data
.f
[c
] = -op
[0]->value
.f
[c
];
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
) {
212 data
.u
[c
] = op
[0]->value
.u
[c
];
215 data
.i
[c
] = op
[0]->value
.i
[c
];
217 data
.i
[c
] = -data
.i
[c
];
219 case GLSL_TYPE_FLOAT
:
220 data
.f
[c
] = fabs(op
[0]->value
.f
[c
]);
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
) {
233 if (op
[0]->value
.u
[c
] != 0.0)
234 data
.u
[c
] = 1 / op
[0]->value
.u
[c
];
237 if (op
[0]->value
.i
[c
] != 0.0)
238 data
.i
[c
] = 1 / op
[0]->value
.i
[c
];
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
];
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
]);
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
]);
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
]);
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
]);
280 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
281 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
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
) {
291 data
.u
[c
] = op
[0]->value
.u
[c
] + op
[1]->value
.u
[c
];
294 data
.i
[c
] = op
[0]->value
.i
[c
] + op
[1]->value
.i
[c
];
296 case GLSL_TYPE_FLOAT
:
297 data
.f
[c
] = op
[0]->value
.f
[c
] + op
[1]->value
.f
[c
];
304 /* FINISHME: Support operations with non-equal types. */
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
) {
313 data
.u
[c
] = op
[0]->value
.u
[c
] - op
[1]->value
.u
[c
];
316 data
.i
[c
] = op
[0]->value
.i
[c
] - op
[1]->value
.i
[c
];
318 case GLSL_TYPE_FLOAT
:
319 data
.f
[c
] = op
[0]->value
.f
[c
] - op
[1]->value
.f
[c
];
326 /* FINISHME: Support operations with non-equal types. */
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
) {
336 data
.u
[c
] = op
[0]->value
.u
[c
] * op
[1]->value
.u
[c
];
339 data
.i
[c
] = op
[0]->value
.i
[c
] * op
[1]->value
.i
[c
];
341 case GLSL_TYPE_FLOAT
:
342 data
.f
[c
] = op
[0]->value
.f
[c
] * op
[1]->value
.f
[c
];
349 /* FINISHME: Support operations with non-equal types. */
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
) {
358 data
.u
[c
] = op
[0]->value
.u
[c
] / op
[1]->value
.u
[c
];
361 data
.i
[c
] = op
[0]->value
.i
[c
] / op
[1]->value
.i
[c
];
363 case GLSL_TYPE_FLOAT
:
364 data
.f
[c
] = op
[0]->value
.f
[c
] / op
[1]->value
.f
[c
];
371 /* FINISHME: Support operations with non-equal types. */
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
];
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
];
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
];
392 switch (ir
->operands
[0]->type
->base_type
) {
394 data
.b
[0] = op
[0]->value
.u
[0] < op
[1]->value
.u
[0];
397 data
.b
[0] = op
[0]->value
.i
[0] < op
[1]->value
.i
[0];
399 case GLSL_TYPE_FLOAT
:
400 data
.b
[0] = op
[0]->value
.f
[0] < op
[1]->value
.f
[0];
406 case ir_binop_greater
:
407 switch (ir
->operands
[0]->type
->base_type
) {
409 data
.b
[0] = op
[0]->value
.u
[0] > op
[1]->value
.u
[0];
412 data
.b
[0] = op
[0]->value
.i
[0] > op
[1]->value
.i
[0];
414 case GLSL_TYPE_FLOAT
:
415 data
.b
[0] = op
[0]->value
.f
[0] > op
[1]->value
.f
[0];
421 case ir_binop_lequal
:
422 switch (ir
->operands
[0]->type
->base_type
) {
424 data
.b
[0] = op
[0]->value
.u
[0] <= op
[1]->value
.u
[0];
427 data
.b
[0] = op
[0]->value
.i
[0] <= op
[1]->value
.i
[0];
429 case GLSL_TYPE_FLOAT
:
430 data
.b
[0] = op
[0]->value
.f
[0] <= op
[1]->value
.f
[0];
436 case ir_binop_gequal
:
437 switch (ir
->operands
[0]->type
->base_type
) {
439 data
.b
[0] = op
[0]->value
.u
[0] >= op
[1]->value
.u
[0];
442 data
.b
[0] = op
[0]->value
.i
[0] >= op
[1]->value
.i
[0];
444 case GLSL_TYPE_FLOAT
:
445 data
.b
[0] = op
[0]->value
.f
[0] >= op
[1]->value
.f
[0];
454 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
455 switch (ir
->operands
[0]->type
->base_type
) {
457 data
.b
[0] = data
.b
[0] && op
[0]->value
.u
[c
] == op
[1]->value
.u
[c
];
460 data
.b
[0] = data
.b
[0] && op
[0]->value
.i
[c
] == op
[1]->value
.i
[c
];
462 case GLSL_TYPE_FLOAT
:
463 data
.b
[0] = data
.b
[0] && op
[0]->value
.f
[c
] == op
[1]->value
.f
[c
];
466 data
.b
[0] = data
.b
[0] && op
[0]->value
.b
[c
] == op
[1]->value
.b
[c
];
473 case ir_binop_nequal
:
475 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
476 switch (ir
->operands
[0]->type
->base_type
) {
478 data
.b
[0] = data
.b
[0] || op
[0]->value
.u
[c
] != op
[1]->value
.u
[c
];
481 data
.b
[0] = data
.b
[0] || op
[0]->value
.i
[c
] != op
[1]->value
.i
[c
];
483 case GLSL_TYPE_FLOAT
:
484 data
.b
[0] = data
.b
[0] || op
[0]->value
.f
[c
] != op
[1]->value
.f
[c
];
487 data
.b
[0] = data
.b
[0] || op
[0]->value
.b
[c
] != op
[1]->value
.b
[c
];
496 /* FINISHME: Should handle all expression types. */
500 this->value
= new ir_constant(ir
->type
, &data
);
505 ir_constant_visitor::visit(ir_texture
*ir
)
507 // FINISHME: Do stuff with texture lookups
514 ir_constant_visitor::visit(ir_swizzle
*ir
)
516 ir_constant
*v
= ir
->val
->constant_expression_value();
521 ir_constant_data data
;
523 const unsigned swiz_idx
[4] = {
524 ir
->mask
.x
, ir
->mask
.y
, ir
->mask
.z
, ir
->mask
.w
527 for (unsigned i
= 0; i
< ir
->mask
.num_components
; i
++) {
528 switch (v
->type
->base_type
) {
530 case GLSL_TYPE_INT
: data
.u
[i
] = v
->value
.u
[swiz_idx
[i
]]; break;
531 case GLSL_TYPE_FLOAT
: data
.f
[i
] = v
->value
.f
[swiz_idx
[i
]]; break;
532 case GLSL_TYPE_BOOL
: data
.b
[i
] = v
->value
.b
[swiz_idx
[i
]]; break;
533 default: assert(!"Should not get here."); break;
537 this->value
= new ir_constant(ir
->type
, &data
);
543 ir_constant_visitor::visit(ir_dereference_variable
*ir
)
547 ir_variable
*var
= ir
->variable_referenced();
548 if (var
&& var
->constant_value
)
549 value
= var
->constant_value
->clone();
554 ir_constant_visitor::visit(ir_dereference_array
*ir
)
556 ir_constant
*array
= ir
->array
->constant_expression_value();
557 ir_constant
*idx
= ir
->array_index
->constant_expression_value();
561 if ((array
!= NULL
) && (idx
!= NULL
)) {
562 if (array
->type
->is_matrix()) {
563 /* Array access of a matrix results in a vector.
565 const unsigned column
= idx
->value
.u
[0];
567 const glsl_type
*const column_type
= array
->type
->column_type();
569 /* Offset in the constant matrix to the first element of the column
572 const unsigned mat_idx
= column
* column_type
->vector_elements
;
574 ir_constant_data data
;
576 switch (column_type
->base_type
) {
579 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
580 data
.u
[i
] = array
->value
.u
[mat_idx
+ i
];
584 case GLSL_TYPE_FLOAT
:
585 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
586 data
.f
[i
] = array
->value
.f
[mat_idx
+ i
];
591 assert(!"Should not get here.");
595 this->value
= new ir_constant(column_type
, &data
);
596 } else if (array
->type
->is_vector()) {
597 const unsigned component
= idx
->value
.u
[0];
599 this->value
= new ir_constant(array
, component
);
601 /* FINISHME: Handle access of constant arrays. */
608 ir_constant_visitor::visit(ir_dereference_record
*ir
)
610 ir_constant
*v
= ir
->record
->constant_expression_value();
612 this->value
= (v
!= NULL
) ? v
->get_record_field(ir
->field
) : NULL
;
617 ir_constant_visitor::visit(ir_assignment
*ir
)
625 ir_constant_visitor::visit(ir_constant
*ir
)
632 ir_constant_visitor::visit(ir_call
*ir
)
640 ir_constant_visitor::visit(ir_return
*ir
)
648 ir_constant_visitor::visit(ir_if
*ir
)
656 ir_constant_visitor::visit(ir_loop
*ir
)
664 ir_constant_visitor::visit(ir_loop_jump
*ir
)