blob: a94b0fc9e2a3baf9900f1fa109d1347dc04c1868 [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
37#include "ir.h"
38#include "ir_visitor.h"
Eric Anholta576f9d2010-03-31 16:25:12 -100039#include "glsl_types.h"
Ian Romanick1cf43a42010-03-30 16:56:50 -070040
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_label *);
67 virtual void visit(ir_function_signature *);
68 virtual void visit(ir_function *);
69 virtual void visit(ir_expression *);
70 virtual void visit(ir_swizzle *);
71 virtual void visit(ir_dereference *);
72 virtual void visit(ir_assignment *);
73 virtual void visit(ir_constant *);
74 virtual void visit(ir_call *);
75 virtual void visit(ir_return *);
76 virtual void visit(ir_if *);
Ian Romanickfad607a2010-04-05 16:16:07 -070077 virtual void visit(ir_loop *);
Ian Romanick1cf43a42010-03-30 16:56:50 -070078 /*@}*/
79
80 /**
81 * Value of the constant expression.
82 *
83 * \note
84 * This field will be \c NULL if the expression is not constant valued.
85 */
86 /* FINIHSME: This cannot hold values for constant arrays or structures. */
87 ir_constant *value;
88};
89
90
91ir_constant *
92ir_instruction::constant_expression_value()
93{
94 ir_constant_visitor visitor;
95
96 this->accept(& visitor);
97 return visitor.value;
98}
99
100
101void
102ir_constant_visitor::visit(ir_variable *ir)
103{
104 (void) ir;
105 value = NULL;
106}
107
108
109void
110ir_constant_visitor::visit(ir_label *ir)
111{
112 (void) ir;
113 value = NULL;
114}
115
116
117void
118ir_constant_visitor::visit(ir_function_signature *ir)
119{
120 (void) ir;
121 value = NULL;
122}
123
124
125void
126ir_constant_visitor::visit(ir_function *ir)
127{
128 (void) ir;
129 value = NULL;
130}
131
Ian Romanick1cf43a42010-03-30 16:56:50 -0700132void
133ir_constant_visitor::visit(ir_expression *ir)
134{
Ian Romanick1cf43a42010-03-30 16:56:50 -0700135 value = NULL;
Eric Anholta576f9d2010-03-31 16:25:12 -1000136 ir_constant *op[2];
Eric Anholtd98da972010-04-01 18:25:11 -1000137 unsigned int operand, c;
138 unsigned u[16];
139 int i[16];
140 float f[16];
141 bool b[16];
142 const glsl_type *type = NULL;
Eric Anholt160d0922010-04-01 18:07:08 -1000143
Eric Anholtd98da972010-04-01 18:25:11 -1000144 for (operand = 0; operand < ir->get_num_operands(); operand++) {
145 op[operand] = ir->operands[operand]->constant_expression_value();
146 if (!op[operand])
Eric Anholt160d0922010-04-01 18:07:08 -1000147 return;
148 }
Eric Anholta576f9d2010-03-31 16:25:12 -1000149
150 switch (ir->operation) {
Eric Anholt528bb852010-03-31 21:09:02 -1000151 case ir_unop_logic_not:
Eric Anholtd98da972010-04-01 18:25:11 -1000152 type = ir->operands[0]->type;
153 assert(type->base_type == GLSL_TYPE_BOOL);
154 for (c = 0; c < ir->operands[0]->type->components(); c++)
155 b[c] = !op[0]->value.b[c];
Eric Anholt528bb852010-03-31 21:09:02 -1000156 break;
Eric Anholtaf186412010-04-06 10:53:57 -0700157
158 case ir_unop_f2i:
159 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
160 type = ir->type;
161 for (c = 0; c < ir->operands[0]->type->components(); c++) {
162 i[c] = op[0]->value.f[c];
163 }
164 break;
165 case ir_unop_i2f:
166 assert(op[0]->type->base_type == GLSL_TYPE_UINT ||
167 op[0]->type->base_type == GLSL_TYPE_INT);
168 type = ir->type;
169 for (c = 0; c < ir->operands[0]->type->components(); c++) {
170 if (op[0]->type->base_type == GLSL_TYPE_INT)
171 f[c] = op[0]->value.i[c];
172 else
173 f[c] = op[0]->value.u[c];
174 }
175 break;
176
Eric Anholtd251b922010-04-01 18:35:42 -1000177 case ir_binop_add:
178 if (ir->operands[0]->type == ir->operands[1]->type) {
179 type = ir->operands[0]->type;
180 for (c = 0; c < ir->operands[0]->type->components(); c++) {
181 switch (ir->operands[0]->type->base_type) {
182 case GLSL_TYPE_UINT:
183 u[c] = op[0]->value.u[c] + op[1]->value.u[c];
184 break;
185 case GLSL_TYPE_INT:
186 i[c] = op[0]->value.i[c] + op[1]->value.i[c];
187 break;
188 case GLSL_TYPE_FLOAT:
189 f[c] = op[0]->value.f[c] + op[1]->value.f[c];
190 break;
191 default:
192 assert(0);
193 }
194 }
195 }
196 break;
197 case ir_binop_sub:
198 if (ir->operands[0]->type == ir->operands[1]->type) {
199 type = ir->operands[0]->type;
200 for (c = 0; c < ir->operands[0]->type->components(); c++) {
201 switch (ir->operands[0]->type->base_type) {
202 case GLSL_TYPE_UINT:
203 u[c] = op[0]->value.u[c] - op[1]->value.u[c];
204 break;
205 case GLSL_TYPE_INT:
206 i[c] = op[0]->value.i[c] - op[1]->value.i[c];
207 break;
208 case GLSL_TYPE_FLOAT:
209 f[c] = op[0]->value.f[c] - op[1]->value.f[c];
210 break;
211 default:
212 assert(0);
213 }
214 }
215 }
216 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000217 case ir_binop_mul:
Eric Anholtd98da972010-04-01 18:25:11 -1000218 if (ir->operands[0]->type == ir->operands[1]->type &&
219 !ir->operands[0]->type->is_matrix()) {
220 type = ir->operands[0]->type;
221 for (c = 0; c < ir->operands[0]->type->components(); c++) {
222 switch (ir->operands[0]->type->base_type) {
223 case GLSL_TYPE_UINT:
224 u[c] = op[0]->value.u[c] * op[1]->value.u[c];
225 break;
226 case GLSL_TYPE_INT:
227 i[c] = op[0]->value.i[c] * op[1]->value.i[c];
228 break;
229 case GLSL_TYPE_FLOAT:
230 f[c] = op[0]->value.f[c] * op[1]->value.f[c];
231 break;
232 default:
233 assert(0);
234 }
Eric Anholta576f9d2010-03-31 16:25:12 -1000235 }
236 }
237 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000238 case ir_binop_div:
239 if (ir->operands[0]->type == ir->operands[1]->type) {
240 type = ir->operands[0]->type;
241 for (c = 0; c < ir->operands[0]->type->components(); c++) {
242 switch (ir->operands[0]->type->base_type) {
243 case GLSL_TYPE_UINT:
244 u[c] = op[0]->value.u[c] / op[1]->value.u[c];
245 break;
246 case GLSL_TYPE_INT:
247 i[c] = op[0]->value.i[c] / op[1]->value.i[c];
248 break;
249 case GLSL_TYPE_FLOAT:
250 f[c] = op[0]->value.f[c] / op[1]->value.f[c];
251 break;
252 default:
253 assert(0);
254 }
255 }
256 }
257 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000258 case ir_binop_logic_and:
Eric Anholtd98da972010-04-01 18:25:11 -1000259 type = ir->operands[0]->type;
260 assert(type->base_type == GLSL_TYPE_BOOL);
261 for (c = 0; c < ir->operands[0]->type->components(); c++)
262 b[c] = op[0]->value.b[c] && op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000263 break;
Eric Anholtd251b922010-04-01 18:35:42 -1000264 case ir_binop_logic_xor:
265 type = ir->operands[0]->type;
266 assert(type->base_type == GLSL_TYPE_BOOL);
267 for (c = 0; c < ir->operands[0]->type->components(); c++)
268 b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
269 break;
Eric Anholta576f9d2010-03-31 16:25:12 -1000270 case ir_binop_logic_or:
Eric Anholtd98da972010-04-01 18:25:11 -1000271 type = ir->operands[0]->type;
272 assert(type->base_type == GLSL_TYPE_BOOL);
273 for (c = 0; c < ir->operands[0]->type->components(); c++)
274 b[c] = op[0]->value.b[c] || op[1]->value.b[c];
Eric Anholta576f9d2010-03-31 16:25:12 -1000275 break;
Eric Anholt85171c22010-04-06 09:55:45 -0700276
277 case ir_binop_less:
278 type = glsl_type::bool_type;
279 switch (ir->operands[0]->type->base_type) {
280 case GLSL_TYPE_UINT:
281 b[0] = op[0]->value.u[0] < op[1]->value.u[0];
282 break;
283 case GLSL_TYPE_INT:
284 b[0] = op[0]->value.i[0] < op[1]->value.i[0];
285 break;
286 case GLSL_TYPE_FLOAT:
287 b[0] = op[0]->value.f[0] < op[1]->value.f[0];
288 break;
289 default:
290 assert(0);
291 }
292 break;
293 case ir_binop_greater:
294 type = glsl_type::bool_type;
295 switch (ir->operands[0]->type->base_type) {
296 case GLSL_TYPE_UINT:
297 b[0] = op[0]->value.u[0] > op[1]->value.u[0];
298 break;
299 case GLSL_TYPE_INT:
300 b[0] = op[0]->value.i[0] > op[1]->value.i[0];
301 break;
302 case GLSL_TYPE_FLOAT:
303 b[0] = op[0]->value.f[0] > op[1]->value.f[0];
304 break;
305 default:
306 assert(0);
307 }
308 break;
309 case ir_binop_lequal:
310 type = glsl_type::bool_type;
311 switch (ir->operands[0]->type->base_type) {
312 case GLSL_TYPE_UINT:
313 b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
314 break;
315 case GLSL_TYPE_INT:
316 b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
317 break;
318 case GLSL_TYPE_FLOAT:
319 b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
320 break;
321 default:
322 assert(0);
323 }
324 break;
325 case ir_binop_gequal:
326 type = glsl_type::bool_type;
327 switch (ir->operands[0]->type->base_type) {
328 case GLSL_TYPE_UINT:
329 b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
330 break;
331 case GLSL_TYPE_INT:
332 b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
333 break;
334 case GLSL_TYPE_FLOAT:
335 b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
336 break;
337 default:
338 assert(0);
339 }
340 break;
341
Eric Anholtec1949e2010-04-06 10:02:27 -0700342 case ir_binop_equal:
343 if (ir->operands[0]->type == ir->operands[1]->type) {
344 type = glsl_type::bool_type;
345 b[0] = true;
346 for (c = 0; c < ir->operands[0]->type->components(); c++) {
347 switch (ir->operands[0]->type->base_type) {
348 case GLSL_TYPE_UINT:
349 b[0] = b[0] && op[0]->value.u[c] == op[1]->value.u[c];
350 break;
351 case GLSL_TYPE_INT:
352 b[0] = b[0] && op[0]->value.i[c] == op[1]->value.i[c];
353 break;
354 case GLSL_TYPE_FLOAT:
355 b[0] = b[0] && op[0]->value.f[c] == op[1]->value.f[c];
356 break;
357 default:
358 assert(0);
359 }
360 }
361 }
362 break;
363 case ir_binop_nequal:
364 if (ir->operands[0]->type == ir->operands[1]->type) {
365 type = glsl_type::bool_type;
366 b[0] = false;
367 for (c = 0; c < ir->operands[0]->type->components(); c++) {
368 switch (ir->operands[0]->type->base_type) {
369 case GLSL_TYPE_UINT:
370 b[0] = b[0] || op[0]->value.u[c] != op[1]->value.u[c];
371 break;
372 case GLSL_TYPE_INT:
373 b[0] = b[0] || op[0]->value.i[c] != op[1]->value.i[c];
374 break;
375 case GLSL_TYPE_FLOAT:
376 b[0] = b[0] || op[0]->value.f[c] != op[1]->value.f[c];
377 break;
378 default:
379 assert(0);
380 }
381 }
382 }
383 break;
384
Eric Anholta576f9d2010-03-31 16:25:12 -1000385 default:
386 break;
387 }
Eric Anholtd98da972010-04-01 18:25:11 -1000388
389 if (type) {
390 switch (type->base_type) {
391 case GLSL_TYPE_UINT:
392 value = new ir_constant(type, u);
393 break;
394 case GLSL_TYPE_INT:
395 value = new ir_constant(type, i);
396 break;
397 case GLSL_TYPE_FLOAT:
398 value = new ir_constant(type, f);
399 break;
400 case GLSL_TYPE_BOOL:
401 value = new ir_constant(type, b);
402 break;
403 }
404 }
Ian Romanick1cf43a42010-03-30 16:56:50 -0700405}
406
407
408void
409ir_constant_visitor::visit(ir_swizzle *ir)
410{
411 (void) ir;
412 value = NULL;
413}
414
415
416void
417ir_constant_visitor::visit(ir_dereference *ir)
418{
Ian Romanick1cf43a42010-03-30 16:56:50 -0700419 value = NULL;
Eric Anholt326c6762010-04-06 10:30:54 -0700420
421 if (ir->mode == ir_dereference::ir_reference_variable) {
422 ir_variable *var = ir->var->as_variable();
423 if (var && var->constant_value) {
424 value = new ir_constant(ir->type, &var->constant_value->value);
425 }
426 }
427 /* FINISHME: Other dereference modes. */
Ian Romanick1cf43a42010-03-30 16:56:50 -0700428}
429
430
431void
432ir_constant_visitor::visit(ir_assignment *ir)
433{
434 (void) ir;
435 value = NULL;
436}
437
438
439void
440ir_constant_visitor::visit(ir_constant *ir)
441{
442 value = ir;
443}
444
445
446void
447ir_constant_visitor::visit(ir_call *ir)
448{
449 (void) ir;
450 value = NULL;
451}
452
453
454void
455ir_constant_visitor::visit(ir_return *ir)
456{
457 (void) ir;
458 value = NULL;
459}
460
461
462void
463ir_constant_visitor::visit(ir_if *ir)
464{
465 (void) ir;
466 value = NULL;
467}
Ian Romanickfad607a2010-04-05 16:16:07 -0700468
469
470void
471ir_constant_visitor::visit(ir_loop *ir)
472{
473 (void) ir;
474 value = NULL;
475}