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_discard
*);
79 virtual void visit(ir_if
*);
80 virtual void visit(ir_loop
*);
81 virtual void visit(ir_loop_jump
*);
85 * Value of the constant expression.
88 * This field will be \c NULL if the expression is not constant valued.
90 /* FINIHSME: This cannot hold values for constant arrays or structures. */
96 ir_instruction::constant_expression_value()
98 ir_constant_visitor visitor
;
100 this->accept(& visitor
);
101 return visitor
.value
;
106 ir_constant_visitor::visit(ir_variable
*ir
)
114 ir_constant_visitor::visit(ir_function_signature
*ir
)
122 ir_constant_visitor::visit(ir_function
*ir
)
129 ir_constant_visitor::visit(ir_expression
*ir
)
132 ir_constant
*op
[2] = { NULL
, NULL
};
133 unsigned int operand
, c
;
134 ir_constant_data data
;
136 memset(&data
, 0, sizeof(data
));
138 for (operand
= 0; operand
< ir
->get_num_operands(); operand
++) {
139 op
[operand
] = ir
->operands
[operand
]->constant_expression_value();
145 assert(op
[0]->type
->base_type
== op
[1]->type
->base_type
);
147 bool op0_scalar
= op
[0]->type
->is_scalar();
148 bool op1_scalar
= op
[1] != NULL
&& op
[1]->type
->is_scalar();
150 /* When iterating over a vector or matrix's components, we want to increase
151 * the loop counter. However, for scalars, we want to stay at 0.
153 unsigned c0_inc
= op0_scalar
? 1 : 0;
154 unsigned c1_inc
= op1_scalar
? 1 : 0;
155 unsigned components
= op
[op1_scalar
? 0 : 1]->type
->components();
157 switch (ir
->operation
) {
158 case ir_unop_logic_not
:
159 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
160 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++)
161 data
.b
[c
] = !op
[0]->value
.b
[c
];
165 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
166 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
167 data
.i
[c
] = op
[0]->value
.f
[c
];
171 assert(op
[0]->type
->base_type
== GLSL_TYPE_UINT
||
172 op
[0]->type
->base_type
== GLSL_TYPE_INT
);
173 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
174 if (op
[0]->type
->base_type
== GLSL_TYPE_INT
)
175 data
.f
[c
] = op
[0]->value
.i
[c
];
177 data
.f
[c
] = op
[0]->value
.u
[c
];
181 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
182 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
183 data
.f
[c
] = op
[0]->value
.b
[c
] ? 1.0 : 0.0;
187 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
188 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
189 data
.b
[c
] = bool(op
[0]->value
.f
[c
]);
193 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
194 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
195 data
.u
[c
] = op
[0]->value
.b
[c
] ? 1 : 0;
199 assert(op
[0]->type
->is_integer());
200 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
201 data
.b
[c
] = bool(op
[0]->value
.u
[c
]);
206 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
207 switch (ir
->type
->base_type
) {
214 case GLSL_TYPE_FLOAT
:
215 data
.f
[c
] = op
[0]->value
.f
[c
] - floor(op
[0]->value
.f
[c
]);
224 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
225 switch (ir
->type
->base_type
) {
227 data
.u
[c
] = -op
[0]->value
.u
[c
];
230 data
.i
[c
] = -op
[0]->value
.i
[c
];
232 case GLSL_TYPE_FLOAT
:
233 data
.f
[c
] = -op
[0]->value
.f
[c
];
242 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
243 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
244 switch (ir
->type
->base_type
) {
246 data
.u
[c
] = op
[0]->value
.u
[c
];
249 data
.i
[c
] = op
[0]->value
.i
[c
];
251 data
.i
[c
] = -data
.i
[c
];
253 case GLSL_TYPE_FLOAT
:
254 data
.f
[c
] = fabs(op
[0]->value
.f
[c
]);
263 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
264 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
265 switch (ir
->type
->base_type
) {
267 if (op
[0]->value
.u
[c
] != 0.0)
268 data
.u
[c
] = 1 / op
[0]->value
.u
[c
];
271 if (op
[0]->value
.i
[c
] != 0.0)
272 data
.i
[c
] = 1 / op
[0]->value
.i
[c
];
274 case GLSL_TYPE_FLOAT
:
275 if (op
[0]->value
.f
[c
] != 0.0)
276 data
.f
[c
] = 1.0 / op
[0]->value
.f
[c
];
285 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
286 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
287 data
.f
[c
] = 1.0 / sqrtf(op
[0]->value
.f
[c
]);
292 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
293 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
294 data
.f
[c
] = sqrtf(op
[0]->value
.f
[c
]);
299 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
300 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
301 data
.f
[c
] = expf(op
[0]->value
.f
[c
]);
306 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
307 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
308 data
.f
[c
] = logf(op
[0]->value
.f
[c
]);
314 assert(op
[0]->type
->base_type
== GLSL_TYPE_FLOAT
);
315 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
321 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
322 for (unsigned c
= 0, c0
= 0, c1
= 0;
324 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
326 switch (ir
->operands
[0]->type
->base_type
) {
328 data
.u
[c
] = op
[0]->value
.u
[c0
] + op
[1]->value
.u
[c1
];
331 data
.i
[c
] = op
[0]->value
.i
[c0
] + op
[1]->value
.i
[c1
];
333 case GLSL_TYPE_FLOAT
:
334 data
.f
[c
] = op
[0]->value
.f
[c0
] + op
[1]->value
.f
[c1
];
343 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
344 for (unsigned c
= 0, c0
= 0, c1
= 0;
346 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
348 switch (ir
->operands
[0]->type
->base_type
) {
350 data
.u
[c
] = op
[0]->value
.u
[c0
] - op
[1]->value
.u
[c1
];
353 data
.i
[c
] = op
[0]->value
.i
[c0
] - op
[1]->value
.i
[c1
];
355 case GLSL_TYPE_FLOAT
:
356 data
.f
[c
] = op
[0]->value
.f
[c0
] - op
[1]->value
.f
[c1
];
365 if (ir
->operands
[0]->type
== ir
->operands
[1]->type
&&
366 !ir
->operands
[0]->type
->is_matrix()) {
367 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
368 switch (ir
->operands
[0]->type
->base_type
) {
370 data
.u
[c
] = op
[0]->value
.u
[c
] * op
[1]->value
.u
[c
];
373 data
.i
[c
] = op
[0]->value
.i
[c
] * op
[1]->value
.i
[c
];
375 case GLSL_TYPE_FLOAT
:
376 data
.f
[c
] = op
[0]->value
.f
[c
] * op
[1]->value
.f
[c
];
383 /* FINISHME: Support operations with non-equal types. */
388 assert(op
[0]->type
== op
[1]->type
|| op0_scalar
|| op1_scalar
);
389 for (unsigned c
= 0, c0
= 0, c1
= 0;
391 c0
+= c0_inc
, c1
+= c1_inc
, c
++) {
393 switch (ir
->operands
[0]->type
->base_type
) {
395 data
.u
[c
] = op
[0]->value
.u
[c0
] / op
[1]->value
.u
[c1
];
398 data
.i
[c
] = op
[0]->value
.i
[c0
] / op
[1]->value
.i
[c1
];
400 case GLSL_TYPE_FLOAT
:
401 data
.f
[c
] = op
[0]->value
.f
[c0
] / op
[1]->value
.f
[c1
];
409 case ir_binop_logic_and
:
410 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
411 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++)
412 data
.b
[c
] = op
[0]->value
.b
[c
] && op
[1]->value
.b
[c
];
414 case ir_binop_logic_xor
:
415 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
416 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++)
417 data
.b
[c
] = op
[0]->value
.b
[c
] ^ op
[1]->value
.b
[c
];
419 case ir_binop_logic_or
:
420 assert(op
[0]->type
->base_type
== GLSL_TYPE_BOOL
);
421 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++)
422 data
.b
[c
] = op
[0]->value
.b
[c
] || op
[1]->value
.b
[c
];
426 switch (ir
->operands
[0]->type
->base_type
) {
428 data
.b
[0] = op
[0]->value
.u
[0] < op
[1]->value
.u
[0];
431 data
.b
[0] = op
[0]->value
.i
[0] < op
[1]->value
.i
[0];
433 case GLSL_TYPE_FLOAT
:
434 data
.b
[0] = op
[0]->value
.f
[0] < op
[1]->value
.f
[0];
440 case ir_binop_greater
:
441 switch (ir
->operands
[0]->type
->base_type
) {
443 data
.b
[0] = op
[0]->value
.u
[0] > op
[1]->value
.u
[0];
446 data
.b
[0] = op
[0]->value
.i
[0] > op
[1]->value
.i
[0];
448 case GLSL_TYPE_FLOAT
:
449 data
.b
[0] = op
[0]->value
.f
[0] > op
[1]->value
.f
[0];
455 case ir_binop_lequal
:
456 switch (ir
->operands
[0]->type
->base_type
) {
458 data
.b
[0] = op
[0]->value
.u
[0] <= op
[1]->value
.u
[0];
461 data
.b
[0] = op
[0]->value
.i
[0] <= op
[1]->value
.i
[0];
463 case GLSL_TYPE_FLOAT
:
464 data
.b
[0] = op
[0]->value
.f
[0] <= op
[1]->value
.f
[0];
470 case ir_binop_gequal
:
471 switch (ir
->operands
[0]->type
->base_type
) {
473 data
.b
[0] = op
[0]->value
.u
[0] >= op
[1]->value
.u
[0];
476 data
.b
[0] = op
[0]->value
.i
[0] >= op
[1]->value
.i
[0];
478 case GLSL_TYPE_FLOAT
:
479 data
.b
[0] = op
[0]->value
.f
[0] >= op
[1]->value
.f
[0];
488 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
489 switch (ir
->operands
[0]->type
->base_type
) {
491 data
.b
[0] = data
.b
[0] && op
[0]->value
.u
[c
] == op
[1]->value
.u
[c
];
494 data
.b
[0] = data
.b
[0] && op
[0]->value
.i
[c
] == op
[1]->value
.i
[c
];
496 case GLSL_TYPE_FLOAT
:
497 data
.b
[0] = data
.b
[0] && op
[0]->value
.f
[c
] == op
[1]->value
.f
[c
];
500 data
.b
[0] = data
.b
[0] && op
[0]->value
.b
[c
] == op
[1]->value
.b
[c
];
507 case ir_binop_nequal
:
509 for (c
= 0; c
< ir
->operands
[0]->type
->components(); c
++) {
510 switch (ir
->operands
[0]->type
->base_type
) {
512 data
.b
[0] = data
.b
[0] || op
[0]->value
.u
[c
] != op
[1]->value
.u
[c
];
515 data
.b
[0] = data
.b
[0] || op
[0]->value
.i
[c
] != op
[1]->value
.i
[c
];
517 case GLSL_TYPE_FLOAT
:
518 data
.b
[0] = data
.b
[0] || op
[0]->value
.f
[c
] != op
[1]->value
.f
[c
];
521 data
.b
[0] = data
.b
[0] || op
[0]->value
.b
[c
] != op
[1]->value
.b
[c
];
530 /* FINISHME: Should handle all expression types. */
534 void *ctx
= talloc_parent(ir
);
535 this->value
= new(ctx
) ir_constant(ir
->type
, &data
);
540 ir_constant_visitor::visit(ir_texture
*ir
)
542 // FINISHME: Do stuff with texture lookups
549 ir_constant_visitor::visit(ir_swizzle
*ir
)
551 ir_constant
*v
= ir
->val
->constant_expression_value();
556 ir_constant_data data
;
558 const unsigned swiz_idx
[4] = {
559 ir
->mask
.x
, ir
->mask
.y
, ir
->mask
.z
, ir
->mask
.w
562 for (unsigned i
= 0; i
< ir
->mask
.num_components
; i
++) {
563 switch (v
->type
->base_type
) {
565 case GLSL_TYPE_INT
: data
.u
[i
] = v
->value
.u
[swiz_idx
[i
]]; break;
566 case GLSL_TYPE_FLOAT
: data
.f
[i
] = v
->value
.f
[swiz_idx
[i
]]; break;
567 case GLSL_TYPE_BOOL
: data
.b
[i
] = v
->value
.b
[swiz_idx
[i
]]; break;
568 default: assert(!"Should not get here."); break;
572 void *ctx
= talloc_parent(ir
);
573 this->value
= new(ctx
) ir_constant(ir
->type
, &data
);
579 ir_constant_visitor::visit(ir_dereference_variable
*ir
)
583 ir_variable
*var
= ir
->variable_referenced();
584 if (var
&& var
->constant_value
)
585 value
= (ir_constant
*)var
->constant_value
->clone(NULL
);
590 ir_constant_visitor::visit(ir_dereference_array
*ir
)
592 void *ctx
= talloc_parent(ir
);
593 ir_constant
*array
= ir
->array
->constant_expression_value();
594 ir_constant
*idx
= ir
->array_index
->constant_expression_value();
598 if ((array
!= NULL
) && (idx
!= NULL
)) {
599 if (array
->type
->is_matrix()) {
600 /* Array access of a matrix results in a vector.
602 const unsigned column
= idx
->value
.u
[0];
604 const glsl_type
*const column_type
= array
->type
->column_type();
606 /* Offset in the constant matrix to the first element of the column
609 const unsigned mat_idx
= column
* column_type
->vector_elements
;
611 ir_constant_data data
;
613 switch (column_type
->base_type
) {
616 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
617 data
.u
[i
] = array
->value
.u
[mat_idx
+ i
];
621 case GLSL_TYPE_FLOAT
:
622 for (unsigned i
= 0; i
< column_type
->vector_elements
; i
++)
623 data
.f
[i
] = array
->value
.f
[mat_idx
+ i
];
628 assert(!"Should not get here.");
632 this->value
= new(ctx
) ir_constant(column_type
, &data
);
633 } else if (array
->type
->is_vector()) {
634 const unsigned component
= idx
->value
.u
[0];
636 this->value
= new(ctx
) ir_constant(array
, component
);
638 /* FINISHME: Handle access of constant arrays. */
645 ir_constant_visitor::visit(ir_dereference_record
*ir
)
647 ir_constant
*v
= ir
->record
->constant_expression_value();
649 this->value
= (v
!= NULL
) ? v
->get_record_field(ir
->field
) : NULL
;
654 ir_constant_visitor::visit(ir_assignment
*ir
)
662 ir_constant_visitor::visit(ir_constant
*ir
)
669 ir_constant_visitor::visit(ir_call
*ir
)
677 ir_constant_visitor::visit(ir_return
*ir
)
685 ir_constant_visitor::visit(ir_discard
*ir
)
693 ir_constant_visitor::visit(ir_if
*ir
)
701 ir_constant_visitor::visit(ir_loop
*ir
)
709 ir_constant_visitor::visit(ir_loop_jump
*ir
)