Replace builtin_types.h generation with the generated output.
[mesa.git] / 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 #define NULL 0
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_swizzle *);
70 virtual void visit(ir_dereference *);
71 virtual void visit(ir_assignment *);
72 virtual void visit(ir_constant *);
73 virtual void visit(ir_call *);
74 virtual void visit(ir_return *);
75 virtual void visit(ir_if *);
76 virtual void visit(ir_loop *);
77 virtual void visit(ir_loop_jump *);
78 /*@}*/
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
91 ir_constant *
92 ir_instruction::constant_expression_value()
93 {
94 ir_constant_visitor visitor;
95
96 this->accept(& visitor);
97 return visitor.value;
98 }
99
100
101 void
102 ir_constant_visitor::visit(ir_variable *ir)
103 {
104 (void) ir;
105 value = NULL;
106 }
107
108
109 void
110 ir_constant_visitor::visit(ir_function_signature *ir)
111 {
112 (void) ir;
113 value = NULL;
114 }
115
116
117 void
118 ir_constant_visitor::visit(ir_function *ir)
119 {
120 (void) ir;
121 value = NULL;
122 }
123
124 void
125 ir_constant_visitor::visit(ir_expression *ir)
126 {
127 value = NULL;
128 ir_constant *op[2];
129 unsigned int operand, c;
130 unsigned u[16];
131 int i[16];
132 float f[16];
133 bool b[16];
134 const glsl_type *type = NULL;
135
136 for (operand = 0; operand < ir->get_num_operands(); operand++) {
137 op[operand] = ir->operands[operand]->constant_expression_value();
138 if (!op[operand])
139 return;
140 }
141
142 switch (ir->operation) {
143 case ir_unop_logic_not:
144 type = ir->operands[0]->type;
145 assert(type->base_type == GLSL_TYPE_BOOL);
146 for (c = 0; c < ir->operands[0]->type->components(); c++)
147 b[c] = !op[0]->value.b[c];
148 break;
149
150 case ir_unop_f2i:
151 assert(op[0]->type->base_type == GLSL_TYPE_FLOAT);
152 type = ir->type;
153 for (c = 0; c < ir->operands[0]->type->components(); c++) {
154 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 type = ir->type;
161 for (c = 0; c < ir->operands[0]->type->components(); c++) {
162 if (op[0]->type->base_type == GLSL_TYPE_INT)
163 f[c] = op[0]->value.i[c];
164 else
165 f[c] = op[0]->value.u[c];
166 }
167 break;
168
169 case ir_binop_add:
170 if (ir->operands[0]->type == ir->operands[1]->type) {
171 type = ir->operands[0]->type;
172 for (c = 0; c < ir->operands[0]->type->components(); c++) {
173 switch (ir->operands[0]->type->base_type) {
174 case GLSL_TYPE_UINT:
175 u[c] = op[0]->value.u[c] + op[1]->value.u[c];
176 break;
177 case GLSL_TYPE_INT:
178 i[c] = op[0]->value.i[c] + op[1]->value.i[c];
179 break;
180 case GLSL_TYPE_FLOAT:
181 f[c] = op[0]->value.f[c] + op[1]->value.f[c];
182 break;
183 default:
184 assert(0);
185 }
186 }
187 }
188 break;
189 case ir_binop_sub:
190 if (ir->operands[0]->type == ir->operands[1]->type) {
191 type = ir->operands[0]->type;
192 for (c = 0; c < ir->operands[0]->type->components(); c++) {
193 switch (ir->operands[0]->type->base_type) {
194 case GLSL_TYPE_UINT:
195 u[c] = op[0]->value.u[c] - op[1]->value.u[c];
196 break;
197 case GLSL_TYPE_INT:
198 i[c] = op[0]->value.i[c] - op[1]->value.i[c];
199 break;
200 case GLSL_TYPE_FLOAT:
201 f[c] = op[0]->value.f[c] - op[1]->value.f[c];
202 break;
203 default:
204 assert(0);
205 }
206 }
207 }
208 break;
209 case ir_binop_mul:
210 if (ir->operands[0]->type == ir->operands[1]->type &&
211 !ir->operands[0]->type->is_matrix()) {
212 type = ir->operands[0]->type;
213 for (c = 0; c < ir->operands[0]->type->components(); c++) {
214 switch (ir->operands[0]->type->base_type) {
215 case GLSL_TYPE_UINT:
216 u[c] = op[0]->value.u[c] * op[1]->value.u[c];
217 break;
218 case GLSL_TYPE_INT:
219 i[c] = op[0]->value.i[c] * op[1]->value.i[c];
220 break;
221 case GLSL_TYPE_FLOAT:
222 f[c] = op[0]->value.f[c] * op[1]->value.f[c];
223 break;
224 default:
225 assert(0);
226 }
227 }
228 }
229 break;
230 case ir_binop_div:
231 if (ir->operands[0]->type == ir->operands[1]->type) {
232 type = ir->operands[0]->type;
233 for (c = 0; c < ir->operands[0]->type->components(); c++) {
234 switch (ir->operands[0]->type->base_type) {
235 case GLSL_TYPE_UINT:
236 u[c] = op[0]->value.u[c] / op[1]->value.u[c];
237 break;
238 case GLSL_TYPE_INT:
239 i[c] = op[0]->value.i[c] / op[1]->value.i[c];
240 break;
241 case GLSL_TYPE_FLOAT:
242 f[c] = op[0]->value.f[c] / op[1]->value.f[c];
243 break;
244 default:
245 assert(0);
246 }
247 }
248 }
249 break;
250 case ir_binop_logic_and:
251 type = ir->operands[0]->type;
252 assert(type->base_type == GLSL_TYPE_BOOL);
253 for (c = 0; c < ir->operands[0]->type->components(); c++)
254 b[c] = op[0]->value.b[c] && op[1]->value.b[c];
255 break;
256 case ir_binop_logic_xor:
257 type = ir->operands[0]->type;
258 assert(type->base_type == GLSL_TYPE_BOOL);
259 for (c = 0; c < ir->operands[0]->type->components(); c++)
260 b[c] = op[0]->value.b[c] ^ op[1]->value.b[c];
261 break;
262 case ir_binop_logic_or:
263 type = ir->operands[0]->type;
264 assert(type->base_type == GLSL_TYPE_BOOL);
265 for (c = 0; c < ir->operands[0]->type->components(); c++)
266 b[c] = op[0]->value.b[c] || op[1]->value.b[c];
267 break;
268
269 case ir_binop_less:
270 type = glsl_type::bool_type;
271 switch (ir->operands[0]->type->base_type) {
272 case GLSL_TYPE_UINT:
273 b[0] = op[0]->value.u[0] < op[1]->value.u[0];
274 break;
275 case GLSL_TYPE_INT:
276 b[0] = op[0]->value.i[0] < op[1]->value.i[0];
277 break;
278 case GLSL_TYPE_FLOAT:
279 b[0] = op[0]->value.f[0] < op[1]->value.f[0];
280 break;
281 default:
282 assert(0);
283 }
284 break;
285 case ir_binop_greater:
286 type = glsl_type::bool_type;
287 switch (ir->operands[0]->type->base_type) {
288 case GLSL_TYPE_UINT:
289 b[0] = op[0]->value.u[0] > op[1]->value.u[0];
290 break;
291 case GLSL_TYPE_INT:
292 b[0] = op[0]->value.i[0] > op[1]->value.i[0];
293 break;
294 case GLSL_TYPE_FLOAT:
295 b[0] = op[0]->value.f[0] > op[1]->value.f[0];
296 break;
297 default:
298 assert(0);
299 }
300 break;
301 case ir_binop_lequal:
302 type = glsl_type::bool_type;
303 switch (ir->operands[0]->type->base_type) {
304 case GLSL_TYPE_UINT:
305 b[0] = op[0]->value.u[0] <= op[1]->value.u[0];
306 break;
307 case GLSL_TYPE_INT:
308 b[0] = op[0]->value.i[0] <= op[1]->value.i[0];
309 break;
310 case GLSL_TYPE_FLOAT:
311 b[0] = op[0]->value.f[0] <= op[1]->value.f[0];
312 break;
313 default:
314 assert(0);
315 }
316 break;
317 case ir_binop_gequal:
318 type = glsl_type::bool_type;
319 switch (ir->operands[0]->type->base_type) {
320 case GLSL_TYPE_UINT:
321 b[0] = op[0]->value.u[0] >= op[1]->value.u[0];
322 break;
323 case GLSL_TYPE_INT:
324 b[0] = op[0]->value.i[0] >= op[1]->value.i[0];
325 break;
326 case GLSL_TYPE_FLOAT:
327 b[0] = op[0]->value.f[0] >= op[1]->value.f[0];
328 break;
329 default:
330 assert(0);
331 }
332 break;
333
334 case ir_binop_equal:
335 if (ir->operands[0]->type == ir->operands[1]->type) {
336 type = glsl_type::bool_type;
337 b[0] = true;
338 for (c = 0; c < ir->operands[0]->type->components(); c++) {
339 switch (ir->operands[0]->type->base_type) {
340 case GLSL_TYPE_UINT:
341 b[0] = b[0] && op[0]->value.u[c] == op[1]->value.u[c];
342 break;
343 case GLSL_TYPE_INT:
344 b[0] = b[0] && op[0]->value.i[c] == op[1]->value.i[c];
345 break;
346 case GLSL_TYPE_FLOAT:
347 b[0] = b[0] && op[0]->value.f[c] == op[1]->value.f[c];
348 break;
349 case GLSL_TYPE_BOOL:
350 b[0] = b[0] && op[0]->value.b[c] == op[1]->value.b[c];
351 break;
352 default:
353 assert(0);
354 }
355 }
356 }
357 break;
358 case ir_binop_nequal:
359 if (ir->operands[0]->type == ir->operands[1]->type) {
360 type = glsl_type::bool_type;
361 b[0] = false;
362 for (c = 0; c < ir->operands[0]->type->components(); c++) {
363 switch (ir->operands[0]->type->base_type) {
364 case GLSL_TYPE_UINT:
365 b[0] = b[0] || op[0]->value.u[c] != op[1]->value.u[c];
366 break;
367 case GLSL_TYPE_INT:
368 b[0] = b[0] || op[0]->value.i[c] != op[1]->value.i[c];
369 break;
370 case GLSL_TYPE_FLOAT:
371 b[0] = b[0] || op[0]->value.f[c] != op[1]->value.f[c];
372 break;
373 case GLSL_TYPE_BOOL:
374 b[0] = b[0] || op[0]->value.b[c] != op[1]->value.b[c];
375 break;
376 default:
377 assert(0);
378 }
379 }
380 }
381 break;
382
383 default:
384 break;
385 }
386
387 if (type) {
388 switch (type->base_type) {
389 case GLSL_TYPE_UINT:
390 value = new ir_constant(type, u);
391 break;
392 case GLSL_TYPE_INT:
393 value = new ir_constant(type, i);
394 break;
395 case GLSL_TYPE_FLOAT:
396 value = new ir_constant(type, f);
397 break;
398 case GLSL_TYPE_BOOL:
399 value = new ir_constant(type, b);
400 break;
401 }
402 }
403 }
404
405
406 void
407 ir_constant_visitor::visit(ir_swizzle *ir)
408 {
409 (void) ir;
410 value = NULL;
411 }
412
413
414 void
415 ir_constant_visitor::visit(ir_dereference *ir)
416 {
417 value = NULL;
418
419 if (ir->mode == ir_dereference::ir_reference_variable) {
420 ir_variable *var = ir->var->as_variable();
421 if (var && var->constant_value) {
422 value = new ir_constant(ir->type, &var->constant_value->value);
423 }
424 }
425 /* FINISHME: Other dereference modes. */
426 }
427
428
429 void
430 ir_constant_visitor::visit(ir_assignment *ir)
431 {
432 (void) ir;
433 value = NULL;
434 }
435
436
437 void
438 ir_constant_visitor::visit(ir_constant *ir)
439 {
440 value = ir;
441 }
442
443
444 void
445 ir_constant_visitor::visit(ir_call *ir)
446 {
447 (void) ir;
448 value = NULL;
449 }
450
451
452 void
453 ir_constant_visitor::visit(ir_return *ir)
454 {
455 (void) ir;
456 value = NULL;
457 }
458
459
460 void
461 ir_constant_visitor::visit(ir_if *ir)
462 {
463 (void) ir;
464 value = NULL;
465 }
466
467
468 void
469 ir_constant_visitor::visit(ir_loop *ir)
470 {
471 (void) ir;
472 value = NULL;
473 }
474
475
476 void
477 ir_constant_visitor::visit(ir_loop_jump *ir)
478 {
479 (void) ir;
480 value = NULL;
481 }