blob: 361a7a1630a6e5801b6716c513cd81541415cac4 [file] [log] [blame]
Ian Romanick1cf43a42010-03-30 16:56:50 -07001/*
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#define NULL 0
Eric Anholt43ad37a2010-05-12 14:42:21 -070037#include <math.h>
Ian Romanick1cf43a42010-03-30 16:56:50 -070038#include "ir.h"
39#include "ir_visitor.h"
Eric Anholta576f9d2010-03-31 16:25:12 -100040#include "glsl_types.h"
Ian Romanick1cf43a42010-03-30 16:56:50 -070041
42/**
43 * Visitor class for evaluating constant expressions
44 */
45class ir_constant_visitor : public ir_visitor {
46public:
47 ir_constant_visitor()
48 : value(NULL)
49 {
50 /* empty */
51 }
52
53 virtual ~ir_constant_visitor()
54 {
55 /* empty */
56 }
57
58 /**
59 * \name Visit methods
60 *
61 * As typical for the visitor pattern, there must be one \c visit method for
62 * each concrete subclass of \c ir_instruction. Virtual base classes within
63 * the hierarchy should not have \c visit methods.
64 */
65 /*@{*/
66 virtual void visit(ir_variable *);
Ian Romanick1cf43a42010-03-30 16:56:50 -070067 virtual void visit(ir_function_signature *);
68 virtual void visit(ir_function *);
69 virtual void visit(ir_expression *);
70 virtual void visit(ir_swizzle *);
Ian Romanickc7b10462010-05-19 13:20:12 +020071 virtual void visit(ir_dereference_variable *);
72 virtual void visit(ir_dereference_array *);
73 virtual void visit(ir_dereference_record *);
Ian Romanick1cf43a42010-03-30 16:56:50 -070074 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 *);
Ian Romanickfad607a2010-04-05 16:16:07 -070079 virtual void visit(ir_loop *);
Ian Romanickf8e31e02010-04-05 16:28:15 -070080 virtual void visit(ir_loop_jump *);
Ian Romanick1cf43a42010-03-30 16:56:50 -070081 /*@}*/
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
Ian Romanick1cf43a42010-03-30 16:56:50 -0700113ir_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
Ian Romanick1cf43a42010-03-30 16:56:50 -0700127void
128ir_constant_visitor::visit(ir_expression *ir)
129{
Ian Romanick1cf43a42010-03-30 16:56:50 -0700130 value = NULL;
Eric Anholta576f9d2010-03-31 16:25:12 -1000131 ir_constant *op[2];
Eric Anholtd98da972010-04-01 18:25:11 -1000132 unsigned int operand, c;
133 unsigned u[16];
134 int i[16];
135 float f[16];
136 bool b[16];
137 const glsl_type *type = NULL;
Eric Anholt160d0922010-04-01 18:07:08 -1000138
Eric Anholtd98da972010-04-01 18:25:11 -1000139 for (operand = 0; operand < ir->get_num_operands(); operand++) {
140 op[operand] = ir->operands[operand]->constant_expression_value();
141 if (!op[operand])
Eric Anholt160d0922010-04-01 18:07:08 -1000142 return;
143 }
Eric Anholta576f9d2010-03-31 16:25:12 -1000144
145 switch (ir->operation) {
Eric Anholt528bb852010-03-31 21:09:02 -1000146 case ir_unop_logic_not:
Eric Anholtd98da972010-04-01 18:25:11 -1000147 type = ir->operands[0]->type;
148 assert(type->base_type == GLSL_TYPE_BOOL);
149 for (c = 0; c < ir->operands[0]->type->components(); c++)
150 b[c] = !op[0]->value.b[c];
Eric Anholt528bb852010-03-31 21:09:02 -1000151 break;
Eric Anholtaf186412010-04-06 10:53:57 -0700152
153 case ir_unop_f2i:
154 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
155 type = ir->type;
156 for (c = 0; c < ir->operands[0]->type->components(); c++) {
157 i[c] = op[0]->value.f[c];
158 }
159 break;
160 case ir_unop_i2f:
161 assert(op[0]->type->base_type == GLSL_TYPE_UINT ||
162 op[0]->type->base_type == GLSL_TYPE_INT);
163 type = ir->type;
164 for (c = 0; c < ir->operands[0]->type->components(); c++) {
165 if (op[0]->type->base_type == GLSL_TYPE_INT)
166 f[c] = op[0]->value.i[c];
167 else
168 f[c] = op[0]->value.u[c];
169 }
170 break;
171
Eric Anholt43ad37a2010-05-12 14:42:21 -0700172 case ir_unop_neg:
173 type = ir->type;
174 for (c = 0; c < ir->operands[0]->type->components(); c++) {
175 switch (type->base_type) {
176 case GLSL_TYPE_UINT:
177 u[c] = -op[0]->value.u[c];
178 break;
179 case GLSL_TYPE_INT:
180 i[c] = -op[0]->value.i[c];
181 break;
182 case GLSL_TYPE_FLOAT:
183 f[c] = -op[0]->value.f[c];
184 break;
185 default:
186 assert(0);
187 }
188 }
189 break;
190
191 case ir_unop_abs:
192 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
193 type = ir->type;
194 for (c = 0; c < ir->operands[0]->type->components(); c++) {
195 switch (type->base_type) {
196 case GLSL_TYPE_UINT:
197 u[c] = op[0]->value.u[c];
198 break;
199 case GLSL_TYPE_INT:
200 i[c] = op[0]->value.i[c];
201 if (i[c] < 0)
202 i[c] = -i[c];
203 break;
204 case GLSL_TYPE_FLOAT:
205 f[c] = fabs(op[0]->value.f[c]);
206 break;
207 default:
208 assert(0);
209 }
210 }
211 break;
212
213 case ir_unop_rcp:
214 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
215 type = ir->type;
216 for (c = 0; c < ir->operands[0]->type->components(); c++) {
217 switch (type->base_type) {
218 case GLSL_TYPE_UINT:
219 if (op[0]->value.u[c] != 0.0)
220 u[c] = 1 / op[0]->value.u[c];
221 break;
222 case GLSL_TYPE_INT:
223 if (op[0]->value.i[c] != 0.0)
224 i[c] = 1 / op[0]->value.i[c];
225 break;
226 case GLSL_TYPE_FLOAT:
227 if (op[0]->value.f[c] != 0.0)
228 f[c] = 1.0 / op[0]->value.f[c];
229 break;
230 default:
231 assert(0);
232 }
233 }
234 break;
235
236 case ir_unop_rsq:
237 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
238 type = ir->type;
239 for (c = 0; c < ir->operands[0]->type->components(); c++) {
240 f[c] = 1.0 / sqrtf(op[0]->value.f[c]);
241 }
242 break;
243
244 case ir_unop_sqrt:
245 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
246 type = ir->type;
247 for (c = 0; c < ir->operands[0]->type->components(); c++) {
248 f[c] = sqrtf(op[0]->value.f[c]);
249 }
250 break;
251
252 case ir_unop_exp:
253 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
254 type = ir->type;
255 for (c = 0; c < ir->operands[0]->type->components(); c++) {
256 f[c] = expf(op[0]->value.f[c]);
257 }
258 break;
259
260 case ir_unop_log:
261 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
262 type = ir->type;
263 for (c = 0; c < ir->operands[0]->type->components(); c++) {
264 f[c] = logf(op[0]->value.f[c]);
265 }
266 break;
267
Eric Anholtd251b922010-04-01 18:35:42 -1000268 case ir_binop_add:
269 if (ir->operands[0]->type == ir->operands[1]->type) {
270 type = ir->operands[0]->type;
271 for (c = 0; c < ir->operands[0]->type->components(); c++) {
272 switch (ir->operands[0]->type->base_type) {
273 case GLSL_TYPE_UINT:
274 u[c] = op[0]->value.u[c] + op[1]->value.u[c];
275 break;
276 case GLSL_TYPE_INT:
277 i[c] = op[0]->value.i[c] + op[1]->value.i[c];
278 break;
279 case GLSL_TYPE_FLOAT:
280 f[c] = op[0]->value.f[c] + op[1]->value.f[c];
281 break;
282 default:
283 assert(0);
284 }
285 }
286 }
287 break;
288 case ir_binop_sub:
289 if (ir->operands[0]->type == ir->operands[1]->type) {
290 type = ir->operands[0]->type;
291 for (c = 0; c < ir->operands[0]->type->components(); c++) {
292 switch (ir->operands[0]->type->base_type) {
293 case GLSL_TYPE_UINT:
294 u[c] = op[0]->value.u[c] - op[1]->value.u[c];
295 break;
296 case GLSL_TYPE_INT:
297 i[c] = op[0]->value.i[c] - op[1]->value.i[c];
298 break;
299 case GLSL_TYPE_FLOAT:
300 f[c] = op[0]->value.f[c] - op[1]->value.f[c];
301 break;
302 default:
303 assert(0);
304 }
305 }
306 }
307 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000308 case ir_binop_mul:
Eric Anholtd98da972010-04-01 18:25:11 -1000309 if (ir->operands[0]->type == ir->operands[1]->type &&
310 !ir->operands[0]->type->is_matrix()) {
311 type = ir->operands[0]->type;
312 for (c = 0; c < ir->operands[0]->type->components(); c++) {
313 switch (ir->operands[0]->type->base_type) {
314 case GLSL_TYPE_UINT:
315 u[c] = op[0]->value.u[c] * op[1]->value.u[c];
316 break;
317 case GLSL_TYPE_INT:
318 i[c] = op[0]->value.i[c] * op[1]->value.i[c];
319 break;
320 case GLSL_TYPE_FLOAT:
321 f[c] = op[0]->value.f[c] * op[1]->value.f[c];
322 break;
323 default:
324 assert(0);
325 }
Eric Anholta576f9d2010-03-31 16:25:12 -1000326 }
327 }
328 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000329 case ir_binop_div:
330 if (ir->operands[0]->type == ir->operands[1]->type) {
331 type = ir->operands[0]->type;
332 for (c = 0; c < ir->operands[0]->type->components(); c++) {
333 switch (ir->operands[0]->type->base_type) {
334 case GLSL_TYPE_UINT:
335 u[c] = op[0]->value.u[c] / op[1]->value.u[c];
336 break;
337 case GLSL_TYPE_INT:
338 i[c] = op[0]->value.i[c] / op[1]->value.i[c];
339 break;
340 case GLSL_TYPE_FLOAT:
341 f[c] = op[0]->value.f[c] / op[1]->value.f[c];
342 break;
343 default:
344 assert(0);
345 }
346 }
347 }
348 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000349 case ir_binop_logic_and:
Eric Anholtd98da972010-04-01 18:25:11 -1000350 type = ir->operands[0]->type;
351 assert(type->base_type == GLSL_TYPE_BOOL);
352 for (c = 0; c < ir->operands[0]->type->components(); c++)
353 b[c] = op[0]->value.b[c] && op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000354 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000355 case ir_binop_logic_xor:
356 type = ir->operands[0]->type;
357 assert(type->base_type == GLSL_TYPE_BOOL);
358 for (c = 0; c < ir->operands[0]->type->components(); c++)
359 b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
360 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000361 case ir_binop_logic_or:
Eric Anholtd98da972010-04-01 18:25:11 -1000362 type = ir->operands[0]->type;
363 assert(type->base_type == GLSL_TYPE_BOOL);
364 for (c = 0; c < ir->operands[0]->type->components(); c++)
365 b[c] = op[0]->value.b[c] || op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000366 break;
Eric Anholt85171c22010-04-06 09:55:45 -0700367
368 case ir_binop_less:
369 type = glsl_type::bool_type;
370 switch (ir->operands[0]->type->base_type) {
371 case GLSL_TYPE_UINT:
372 b[0] = op[0]->value.u[0] < op[1]->value.u[0];
373 break;
374 case GLSL_TYPE_INT:
375 b[0] = op[0]->value.i[0] < op[1]->value.i[0];
376 break;
377 case GLSL_TYPE_FLOAT:
378 b[0] = op[0]->value.f[0] < op[1]->value.f[0];
379 break;
380 default:
381 assert(0);
382 }
383 break;
384 case ir_binop_greater:
385 type = glsl_type::bool_type;
386 switch (ir->operands[0]->type->base_type) {
387 case GLSL_TYPE_UINT:
388 b[0] = op[0]->value.u[0] > op[1]->value.u[0];
389 break;
390 case GLSL_TYPE_INT:
391 b[0] = op[0]->value.i[0] > op[1]->value.i[0];
392 break;
393 case GLSL_TYPE_FLOAT:
394 b[0] = op[0]->value.f[0] > op[1]->value.f[0];
395 break;
396 default:
397 assert(0);
398 }
399 break;
400 case ir_binop_lequal:
401 type = glsl_type::bool_type;
402 switch (ir->operands[0]->type->base_type) {
403 case GLSL_TYPE_UINT:
404 b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
405 break;
406 case GLSL_TYPE_INT:
407 b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
408 break;
409 case GLSL_TYPE_FLOAT:
410 b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
411 break;
412 default:
413 assert(0);
414 }
415 break;
416 case ir_binop_gequal:
417 type = glsl_type::bool_type;
418 switch (ir->operands[0]->type->base_type) {
419 case GLSL_TYPE_UINT:
420 b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
421 break;
422 case GLSL_TYPE_INT:
423 b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
424 break;
425 case GLSL_TYPE_FLOAT:
426 b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
427 break;
428 default:
429 assert(0);
430 }
431 break;
432
Eric Anholtec1949e2010-04-06 10:02:27 -0700433 case ir_binop_equal:
434 if (ir->operands[0]->type == ir->operands[1]->type) {
435 type = glsl_type::bool_type;
436 b[0] = true;
437 for (c = 0; c < ir->operands[0]->type->components(); c++) {
438 switch (ir->operands[0]->type->base_type) {
439 case GLSL_TYPE_UINT:
440 b[0] = b[0] && op[0]->value.u[c] == op[1]->value.u[c];
441 break;
442 case GLSL_TYPE_INT:
443 b[0] = b[0] && op[0]->value.i[c] == op[1]->value.i[c];
444 break;
445 case GLSL_TYPE_FLOAT:
446 b[0] = b[0] && op[0]->value.f[c] == op[1]->value.f[c];
447 break;
Ian Romanick77cce642010-04-07 16:48:42 -0700448 case GLSL_TYPE_BOOL:
449 b[0] = b[0] && op[0]->value.b[c] == op[1]->value.b[c];
450 break;
Eric Anholtec1949e2010-04-06 10:02:27 -0700451 default:
452 assert(0);
453 }
454 }
455 }
456 break;
457 case ir_binop_nequal:
458 if (ir->operands[0]->type == ir->operands[1]->type) {
459 type = glsl_type::bool_type;
460 b[0] = false;
461 for (c = 0; c < ir->operands[0]->type->components(); c++) {
462 switch (ir->operands[0]->type->base_type) {
463 case GLSL_TYPE_UINT:
464 b[0] = b[0] || op[0]->value.u[c] != op[1]->value.u[c];
465 break;
466 case GLSL_TYPE_INT:
467 b[0] = b[0] || op[0]->value.i[c] != op[1]->value.i[c];
468 break;
469 case GLSL_TYPE_FLOAT:
470 b[0] = b[0] || op[0]->value.f[c] != op[1]->value.f[c];
471 break;
Ian Romanick77cce642010-04-07 16:48:42 -0700472 case GLSL_TYPE_BOOL:
473 b[0] = b[0] || op[0]->value.b[c] != op[1]->value.b[c];
474 break;
Eric Anholtec1949e2010-04-06 10:02:27 -0700475 default:
476 assert(0);
477 }
478 }
479 }
480 break;
481
Eric Anholta576f9d2010-03-31 16:25:12 -1000482 default:
483 break;
484 }
Eric Anholtd98da972010-04-01 18:25:11 -1000485
486 if (type) {
487 switch (type->base_type) {
488 case GLSL_TYPE_UINT:
489 value = new ir_constant(type, u);
490 break;
491 case GLSL_TYPE_INT:
492 value = new ir_constant(type, i);
493 break;
494 case GLSL_TYPE_FLOAT:
495 value = new ir_constant(type, f);
496 break;
497 case GLSL_TYPE_BOOL:
498 value = new ir_constant(type, b);
499 break;
500 }
501 }
Ian Romanick1cf43a42010-03-30 16:56:50 -0700502}
503
504
505void
506ir_constant_visitor::visit(ir_swizzle *ir)
507{
508 (void) ir;
509 value = NULL;
510}
511
512
513void
Ian Romanickc7b10462010-05-19 13:20:12 +0200514ir_constant_visitor::visit(ir_dereference_variable *ir)
Ian Romanick1cf43a42010-03-30 16:56:50 -0700515{
Ian Romanick1cf43a42010-03-30 16:56:50 -0700516 value = NULL;
Eric Anholt326c6762010-04-06 10:30:54 -0700517
Ian Romanickc7b10462010-05-19 13:20:12 +0200518 ir_variable *var = ir->variable_referenced();
519 if (var && var->constant_value)
520 value = new ir_constant(ir->type, &var->constant_value->value);
521}
522
523
524void
525ir_constant_visitor::visit(ir_dereference_array *ir)
526{
Ian Romanick36ea2862010-05-19 13:52:29 +0200527 (void) ir;
Ian Romanickc7b10462010-05-19 13:20:12 +0200528 value = NULL;
529 /* FINISHME: Other dereference modes. */
530}
531
532
533void
534ir_constant_visitor::visit(ir_dereference_record *ir)
535{
Ian Romanick36ea2862010-05-19 13:52:29 +0200536 (void) ir;
Ian Romanickc7b10462010-05-19 13:20:12 +0200537 value = NULL;
Eric Anholt326c6762010-04-06 10:30:54 -0700538 /* FINISHME: Other dereference modes. */
Ian Romanick1cf43a42010-03-30 16:56:50 -0700539}
540
541
542void
543ir_constant_visitor::visit(ir_assignment *ir)
544{
545 (void) ir;
546 value = NULL;
547}
548
549
550void
551ir_constant_visitor::visit(ir_constant *ir)
552{
553 value = ir;
554}
555
556
557void
558ir_constant_visitor::visit(ir_call *ir)
559{
560 (void) ir;
561 value = NULL;
562}
563
564
565void
566ir_constant_visitor::visit(ir_return *ir)
567{
568 (void) ir;
569 value = NULL;
570}
571
572
573void
574ir_constant_visitor::visit(ir_if *ir)
575{
576 (void) ir;
577 value = NULL;
578}
Ian Romanickfad607a2010-04-05 16:16:07 -0700579
580
581void
582ir_constant_visitor::visit(ir_loop *ir)
583{
584 (void) ir;
585 value = NULL;
586}
Ian Romanickf8e31e02010-04-05 16:28:15 -0700587
588
589void
590ir_constant_visitor::visit(ir_loop_jump *ir)
591{
592 (void) ir;
593 value = NULL;
594}