Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 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 | #include |
||
24 | #include "main/core.h" /* for MAX2 */ |
||
25 | #include "ir.h" |
||
26 | #include "ir_visitor.h" |
||
27 | #include "glsl_types.h" |
||
28 | |||
29 | ir_rvalue::ir_rvalue() |
||
30 | { |
||
31 | this->type = glsl_type::error_type; |
||
32 | } |
||
33 | |||
34 | bool ir_rvalue::is_zero() const |
||
35 | { |
||
36 | return false; |
||
37 | } |
||
38 | |||
39 | bool ir_rvalue::is_one() const |
||
40 | { |
||
41 | return false; |
||
42 | } |
||
43 | |||
44 | bool ir_rvalue::is_negative_one() const |
||
45 | { |
||
46 | return false; |
||
47 | } |
||
48 | |||
49 | /** |
||
50 | * Modify the swizzle make to move one component to another |
||
51 | * |
||
52 | * \param m IR swizzle to be modified |
||
53 | * \param from Component in the RHS that is to be swizzled |
||
54 | * \param to Desired swizzle location of \c from |
||
55 | */ |
||
56 | static void |
||
57 | update_rhs_swizzle(ir_swizzle_mask &m, unsigned from, unsigned to) |
||
58 | { |
||
59 | switch (to) { |
||
60 | case 0: m.x = from; break; |
||
61 | case 1: m.y = from; break; |
||
62 | case 2: m.z = from; break; |
||
63 | case 3: m.w = from; break; |
||
64 | default: assert(!"Should not get here."); |
||
65 | } |
||
66 | |||
67 | m.num_components = MAX2(m.num_components, (to + 1)); |
||
68 | } |
||
69 | |||
70 | void |
||
71 | ir_assignment::set_lhs(ir_rvalue *lhs) |
||
72 | { |
||
73 | void *mem_ctx = this; |
||
74 | bool swizzled = false; |
||
75 | |||
76 | while (lhs != NULL) { |
||
77 | ir_swizzle *swiz = lhs->as_swizzle(); |
||
78 | |||
79 | if (swiz == NULL) |
||
80 | break; |
||
81 | |||
82 | unsigned write_mask = 0; |
||
83 | ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 }; |
||
84 | |||
85 | for (unsigned i = 0; i < swiz->mask.num_components; i++) { |
||
86 | unsigned c = 0; |
||
87 | |||
88 | switch (i) { |
||
89 | case 0: c = swiz->mask.x; break; |
||
90 | case 1: c = swiz->mask.y; break; |
||
91 | case 2: c = swiz->mask.z; break; |
||
92 | case 3: c = swiz->mask.w; break; |
||
93 | default: assert(!"Should not get here."); |
||
94 | } |
||
95 | |||
96 | write_mask |= (((this->write_mask >> i) & 1) << c); |
||
97 | update_rhs_swizzle(rhs_swiz, i, c); |
||
98 | } |
||
99 | |||
100 | this->write_mask = write_mask; |
||
101 | lhs = swiz->val; |
||
102 | |||
103 | this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz); |
||
104 | swizzled = true; |
||
105 | } |
||
106 | |||
107 | if (swizzled) { |
||
108 | /* Now, RHS channels line up with the LHS writemask. Collapse it |
||
109 | * to just the channels that will be written. |
||
110 | */ |
||
111 | ir_swizzle_mask rhs_swiz = { 0, 0, 0, 0, 0, 0 }; |
||
112 | int rhs_chan = 0; |
||
113 | for (int i = 0; i < 4; i++) { |
||
114 | if (write_mask & (1 << i)) |
||
115 | update_rhs_swizzle(rhs_swiz, i, rhs_chan++); |
||
116 | } |
||
117 | this->rhs = new(mem_ctx) ir_swizzle(this->rhs, rhs_swiz); |
||
118 | } |
||
119 | |||
120 | assert((lhs == NULL) || lhs->as_dereference()); |
||
121 | |||
122 | this->lhs = (ir_dereference *) lhs; |
||
123 | } |
||
124 | |||
125 | ir_variable * |
||
126 | ir_assignment::whole_variable_written() |
||
127 | { |
||
128 | ir_variable *v = this->lhs->whole_variable_referenced(); |
||
129 | |||
130 | if (v == NULL) |
||
131 | return NULL; |
||
132 | |||
133 | if (v->type->is_scalar()) |
||
134 | return v; |
||
135 | |||
136 | if (v->type->is_vector()) { |
||
137 | const unsigned mask = (1U << v->type->vector_elements) - 1; |
||
138 | |||
139 | if (mask != this->write_mask) |
||
140 | return NULL; |
||
141 | } |
||
142 | |||
143 | /* Either all the vector components are assigned or the variable is some |
||
144 | * composite type (and the whole thing is assigned. |
||
145 | */ |
||
146 | return v; |
||
147 | } |
||
148 | |||
149 | ir_assignment::ir_assignment(ir_dereference *lhs, ir_rvalue *rhs, |
||
150 | ir_rvalue *condition, unsigned write_mask) |
||
151 | { |
||
152 | this->ir_type = ir_type_assignment; |
||
153 | this->condition = condition; |
||
154 | this->rhs = rhs; |
||
155 | this->lhs = lhs; |
||
156 | this->write_mask = write_mask; |
||
157 | |||
158 | if (lhs->type->is_scalar() || lhs->type->is_vector()) { |
||
159 | int lhs_components = 0; |
||
160 | for (int i = 0; i < 4; i++) { |
||
161 | if (write_mask & (1 << i)) |
||
162 | lhs_components++; |
||
163 | } |
||
164 | |||
165 | assert(lhs_components == this->rhs->type->vector_elements); |
||
166 | } |
||
167 | } |
||
168 | |||
169 | ir_assignment::ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, |
||
170 | ir_rvalue *condition) |
||
171 | { |
||
172 | this->ir_type = ir_type_assignment; |
||
173 | this->condition = condition; |
||
174 | this->rhs = rhs; |
||
175 | |||
176 | /* If the RHS is a vector type, assume that all components of the vector |
||
177 | * type are being written to the LHS. The write mask comes from the RHS |
||
178 | * because we can have a case where the LHS is a vec4 and the RHS is a |
||
179 | * vec3. In that case, the assignment is: |
||
180 | * |
||
181 | * (assign (...) (xyz) (var_ref lhs) (var_ref rhs)) |
||
182 | */ |
||
183 | if (rhs->type->is_vector()) |
||
184 | this->write_mask = (1U << rhs->type->vector_elements) - 1; |
||
185 | else if (rhs->type->is_scalar()) |
||
186 | this->write_mask = 1; |
||
187 | else |
||
188 | this->write_mask = 0; |
||
189 | |||
190 | this->set_lhs(lhs); |
||
191 | } |
||
192 | |||
193 | |||
194 | ir_expression::ir_expression(int op, const struct glsl_type *type, |
||
195 | ir_rvalue *op0) |
||
196 | { |
||
197 | assert(get_num_operands(ir_expression_operation(op)) == 1); |
||
198 | this->ir_type = ir_type_expression; |
||
199 | this->type = type; |
||
200 | this->operation = ir_expression_operation(op); |
||
201 | this->operands[0] = op0; |
||
202 | this->operands[1] = NULL; |
||
203 | this->operands[2] = NULL; |
||
204 | this->operands[3] = NULL; |
||
205 | } |
||
206 | |||
207 | ir_expression::ir_expression(int op, const struct glsl_type *type, |
||
208 | ir_rvalue *op0, ir_rvalue *op1) |
||
209 | { |
||
210 | assert(((op1 == NULL) && (get_num_operands(ir_expression_operation(op)) == 1)) |
||
211 | || (get_num_operands(ir_expression_operation(op)) == 2)); |
||
212 | this->ir_type = ir_type_expression; |
||
213 | this->type = type; |
||
214 | this->operation = ir_expression_operation(op); |
||
215 | this->operands[0] = op0; |
||
216 | this->operands[1] = op1; |
||
217 | this->operands[2] = NULL; |
||
218 | this->operands[3] = NULL; |
||
219 | } |
||
220 | |||
221 | ir_expression::ir_expression(int op, const struct glsl_type *type, |
||
222 | ir_rvalue *op0, ir_rvalue *op1, |
||
223 | ir_rvalue *op2, ir_rvalue *op3) |
||
224 | { |
||
225 | this->ir_type = ir_type_expression; |
||
226 | this->type = type; |
||
227 | this->operation = ir_expression_operation(op); |
||
228 | this->operands[0] = op0; |
||
229 | this->operands[1] = op1; |
||
230 | this->operands[2] = op2; |
||
231 | this->operands[3] = op3; |
||
232 | } |
||
233 | |||
234 | ir_expression::ir_expression(int op, ir_rvalue *op0) |
||
235 | { |
||
236 | this->ir_type = ir_type_expression; |
||
237 | |||
238 | this->operation = ir_expression_operation(op); |
||
239 | this->operands[0] = op0; |
||
240 | this->operands[1] = NULL; |
||
241 | this->operands[2] = NULL; |
||
242 | this->operands[3] = NULL; |
||
243 | |||
244 | assert(op <= ir_last_unop); |
||
245 | |||
246 | switch (this->operation) { |
||
247 | case ir_unop_bit_not: |
||
248 | case ir_unop_logic_not: |
||
249 | case ir_unop_neg: |
||
250 | case ir_unop_abs: |
||
251 | case ir_unop_sign: |
||
252 | case ir_unop_rcp: |
||
253 | case ir_unop_rsq: |
||
254 | case ir_unop_sqrt: |
||
255 | case ir_unop_exp: |
||
256 | case ir_unop_log: |
||
257 | case ir_unop_exp2: |
||
258 | case ir_unop_log2: |
||
259 | case ir_unop_trunc: |
||
260 | case ir_unop_ceil: |
||
261 | case ir_unop_floor: |
||
262 | case ir_unop_fract: |
||
263 | case ir_unop_round_even: |
||
264 | case ir_unop_cos: |
||
265 | case ir_unop_dFdx: |
||
266 | case ir_unop_dFdy: |
||
267 | this->type = op0->type; |
||
268 | break; |
||
269 | |||
270 | case ir_unop_any: |
||
271 | this->type = glsl_type::bool_type; |
||
272 | break; |
||
273 | |||
274 | default: |
||
275 | assert(!"not reached: missing automatic type setup for ir_expression"); |
||
276 | this->type = op0->type; |
||
277 | break; |
||
278 | } |
||
279 | } |
||
280 | |||
281 | ir_expression::ir_expression(int op, ir_rvalue *op0, ir_rvalue *op1) |
||
282 | { |
||
283 | this->ir_type = ir_type_expression; |
||
284 | |||
285 | this->operation = ir_expression_operation(op); |
||
286 | this->operands[0] = op0; |
||
287 | this->operands[1] = op1; |
||
288 | this->operands[2] = NULL; |
||
289 | this->operands[3] = NULL; |
||
290 | |||
291 | assert(op > ir_last_unop); |
||
292 | |||
293 | switch (this->operation) { |
||
294 | case ir_binop_all_equal: |
||
295 | case ir_binop_any_nequal: |
||
296 | this->type = glsl_type::bool_type; |
||
297 | break; |
||
298 | |||
299 | case ir_binop_add: |
||
300 | case ir_binop_sub: |
||
301 | case ir_binop_min: |
||
302 | case ir_binop_max: |
||
303 | case ir_binop_pow: |
||
304 | case ir_binop_mul: |
||
305 | if (op0->type->is_scalar()) { |
||
306 | this->type = op1->type; |
||
307 | } else if (op1->type->is_scalar()) { |
||
308 | this->type = op0->type; |
||
309 | } else { |
||
310 | /* FINISHME: matrix types */ |
||
311 | assert(!op0->type->is_matrix() && !op1->type->is_matrix()); |
||
312 | assert(op0->type == op1->type); |
||
313 | this->type = op0->type; |
||
314 | } |
||
315 | break; |
||
316 | |||
317 | case ir_binop_logic_and: |
||
318 | case ir_binop_logic_or: |
||
319 | if (op0->type->is_scalar()) { |
||
320 | this->type = op1->type; |
||
321 | } else if (op1->type->is_scalar()) { |
||
322 | this->type = op0->type; |
||
323 | } |
||
324 | break; |
||
325 | |||
326 | case ir_binop_dot: |
||
327 | this->type = glsl_type::float_type; |
||
328 | break; |
||
329 | |||
330 | default: |
||
331 | assert(!"not reached: missing automatic type setup for ir_expression"); |
||
332 | this->type = glsl_type::float_type; |
||
333 | } |
||
334 | } |
||
335 | |||
336 | unsigned int |
||
337 | ir_expression::get_num_operands(ir_expression_operation op) |
||
338 | { |
||
339 | assert(op <= ir_last_opcode); |
||
340 | |||
341 | if (op <= ir_last_unop) |
||
342 | return 1; |
||
343 | |||
344 | if (op <= ir_last_binop) |
||
345 | return 2; |
||
346 | |||
347 | if (op == ir_quadop_vector) |
||
348 | return 4; |
||
349 | |||
350 | assert(false); |
||
351 | return 0; |
||
352 | } |
||
353 | |||
354 | static const char *const operator_strs[] = { |
||
355 | "~", |
||
356 | "!", |
||
357 | "neg", |
||
358 | "abs", |
||
359 | "sign", |
||
360 | "rcp", |
||
361 | "rsq", |
||
362 | "sqrt", |
||
363 | "exp", |
||
364 | "log", |
||
365 | "exp2", |
||
366 | "log2", |
||
367 | "f2i", |
||
368 | "i2f", |
||
369 | "f2b", |
||
370 | "b2f", |
||
371 | "i2b", |
||
372 | "b2i", |
||
373 | "u2f", |
||
374 | "any", |
||
375 | "trunc", |
||
376 | "ceil", |
||
377 | "floor", |
||
378 | "fract", |
||
379 | "round_even", |
||
380 | "sin", |
||
381 | "cos", |
||
382 | "sin_reduced", |
||
383 | "cos_reduced", |
||
384 | "dFdx", |
||
385 | "dFdy", |
||
386 | "noise", |
||
387 | "+", |
||
388 | "-", |
||
389 | "*", |
||
390 | "/", |
||
391 | "%", |
||
392 | "<", |
||
393 | ">", |
||
394 | "<=", |
||
395 | ">=", |
||
396 | "==", |
||
397 | "!=", |
||
398 | "all_equal", |
||
399 | "any_nequal", |
||
400 | "<<", |
||
401 | ">>", |
||
402 | "&", |
||
403 | "^", |
||
404 | "|", |
||
405 | "&&", |
||
406 | "^^", |
||
407 | "||", |
||
408 | "dot", |
||
409 | "min", |
||
410 | "max", |
||
411 | "pow", |
||
412 | "vector", |
||
413 | }; |
||
414 | |||
415 | const char *ir_expression::operator_string(ir_expression_operation op) |
||
416 | { |
||
417 | assert((unsigned int) op < Elements(operator_strs)); |
||
418 | assert(Elements(operator_strs) == (ir_quadop_vector + 1)); |
||
419 | return operator_strs[op]; |
||
420 | } |
||
421 | |||
422 | const char *ir_expression::operator_string() |
||
423 | { |
||
424 | return operator_string(this->operation); |
||
425 | } |
||
426 | |||
427 | ir_expression_operation |
||
428 | ir_expression::get_operator(const char *str) |
||
429 | { |
||
430 | const int operator_count = sizeof(operator_strs) / sizeof(operator_strs[0]); |
||
431 | for (int op = 0; op < operator_count; op++) { |
||
432 | if (strcmp(str, operator_strs[op]) == 0) |
||
433 | return (ir_expression_operation) op; |
||
434 | } |
||
435 | return (ir_expression_operation) -1; |
||
436 | } |
||
437 | |||
438 | ir_constant::ir_constant() |
||
439 | { |
||
440 | this->ir_type = ir_type_constant; |
||
441 | } |
||
442 | |||
443 | ir_constant::ir_constant(const struct glsl_type *type, |
||
444 | const ir_constant_data *data) |
||
445 | { |
||
446 | assert((type->base_type >= GLSL_TYPE_UINT) |
||
447 | && (type->base_type <= GLSL_TYPE_BOOL)); |
||
448 | |||
449 | this->ir_type = ir_type_constant; |
||
450 | this->type = type; |
||
451 | memcpy(& this->value, data, sizeof(this->value)); |
||
452 | } |
||
453 | |||
454 | ir_constant::ir_constant(float f) |
||
455 | { |
||
456 | this->ir_type = ir_type_constant; |
||
457 | this->type = glsl_type::float_type; |
||
458 | this->value.f[0] = f; |
||
459 | for (int i = 1; i < 16; i++) { |
||
460 | this->value.f[i] = 0; |
||
461 | } |
||
462 | } |
||
463 | |||
464 | ir_constant::ir_constant(unsigned int u) |
||
465 | { |
||
466 | this->ir_type = ir_type_constant; |
||
467 | this->type = glsl_type::uint_type; |
||
468 | this->value.u[0] = u; |
||
469 | for (int i = 1; i < 16; i++) { |
||
470 | this->value.u[i] = 0; |
||
471 | } |
||
472 | } |
||
473 | |||
474 | ir_constant::ir_constant(int i) |
||
475 | { |
||
476 | this->ir_type = ir_type_constant; |
||
477 | this->type = glsl_type::int_type; |
||
478 | this->value.i[0] = i; |
||
479 | for (int i = 1; i < 16; i++) { |
||
480 | this->value.i[i] = 0; |
||
481 | } |
||
482 | } |
||
483 | |||
484 | ir_constant::ir_constant(bool b) |
||
485 | { |
||
486 | this->ir_type = ir_type_constant; |
||
487 | this->type = glsl_type::bool_type; |
||
488 | this->value.b[0] = b; |
||
489 | for (int i = 1; i < 16; i++) { |
||
490 | this->value.b[i] = false; |
||
491 | } |
||
492 | } |
||
493 | |||
494 | ir_constant::ir_constant(const ir_constant *c, unsigned i) |
||
495 | { |
||
496 | this->ir_type = ir_type_constant; |
||
497 | this->type = c->type->get_base_type(); |
||
498 | |||
499 | switch (this->type->base_type) { |
||
500 | case GLSL_TYPE_UINT: this->value.u[0] = c->value.u[i]; break; |
||
501 | case GLSL_TYPE_INT: this->value.i[0] = c->value.i[i]; break; |
||
502 | case GLSL_TYPE_FLOAT: this->value.f[0] = c->value.f[i]; break; |
||
503 | case GLSL_TYPE_BOOL: this->value.b[0] = c->value.b[i]; break; |
||
504 | default: assert(!"Should not get here."); break; |
||
505 | } |
||
506 | } |
||
507 | |||
508 | ir_constant::ir_constant(const struct glsl_type *type, exec_list *value_list) |
||
509 | { |
||
510 | this->ir_type = ir_type_constant; |
||
511 | this->type = type; |
||
512 | |||
513 | assert(type->is_scalar() || type->is_vector() || type->is_matrix() |
||
514 | || type->is_record() || type->is_array()); |
||
515 | |||
516 | if (type->is_array()) { |
||
517 | this->array_elements = ralloc_array(this, ir_constant *, type->length); |
||
518 | unsigned i = 0; |
||
519 | foreach_list(node, value_list) { |
||
520 | ir_constant *value = (ir_constant *) node; |
||
521 | assert(value->as_constant() != NULL); |
||
522 | |||
523 | this->array_elements[i++] = value; |
||
524 | } |
||
525 | return; |
||
526 | } |
||
527 | |||
528 | /* If the constant is a record, the types of each of the entries in |
||
529 | * value_list must be a 1-for-1 match with the structure components. Each |
||
530 | * entry must also be a constant. Just move the nodes from the value_list |
||
531 | * to the list in the ir_constant. |
||
532 | */ |
||
533 | /* FINISHME: Should there be some type checking and / or assertions here? */ |
||
534 | /* FINISHME: Should the new constant take ownership of the nodes from |
||
535 | * FINISHME: value_list, or should it make copies? |
||
536 | */ |
||
537 | if (type->is_record()) { |
||
538 | value_list->move_nodes_to(& this->components); |
||
539 | return; |
||
540 | } |
||
541 | |||
542 | for (unsigned i = 0; i < 16; i++) { |
||
543 | this->value.u[i] = 0; |
||
544 | } |
||
545 | |||
546 | ir_constant *value = (ir_constant *) (value_list->head); |
||
547 | |||
548 | /* Constructors with exactly one scalar argument are special for vectors |
||
549 | * and matrices. For vectors, the scalar value is replicated to fill all |
||
550 | * the components. For matrices, the scalar fills the components of the |
||
551 | * diagonal while the rest is filled with 0. |
||
552 | */ |
||
553 | if (value->type->is_scalar() && value->next->is_tail_sentinel()) { |
||
554 | if (type->is_matrix()) { |
||
555 | /* Matrix - fill diagonal (rest is already set to 0) */ |
||
556 | assert(type->base_type == GLSL_TYPE_FLOAT); |
||
557 | for (unsigned i = 0; i < type->matrix_columns; i++) |
||
558 | this->value.f[i * type->vector_elements + i] = value->value.f[0]; |
||
559 | } else { |
||
560 | /* Vector or scalar - fill all components */ |
||
561 | switch (type->base_type) { |
||
562 | case GLSL_TYPE_UINT: |
||
563 | case GLSL_TYPE_INT: |
||
564 | for (unsigned i = 0; i < type->components(); i++) |
||
565 | this->value.u[i] = value->value.u[0]; |
||
566 | break; |
||
567 | case GLSL_TYPE_FLOAT: |
||
568 | for (unsigned i = 0; i < type->components(); i++) |
||
569 | this->value.f[i] = value->value.f[0]; |
||
570 | break; |
||
571 | case GLSL_TYPE_BOOL: |
||
572 | for (unsigned i = 0; i < type->components(); i++) |
||
573 | this->value.b[i] = value->value.b[0]; |
||
574 | break; |
||
575 | default: |
||
576 | assert(!"Should not get here."); |
||
577 | break; |
||
578 | } |
||
579 | } |
||
580 | return; |
||
581 | } |
||
582 | |||
583 | if (type->is_matrix() && value->type->is_matrix()) { |
||
584 | assert(value->next->is_tail_sentinel()); |
||
585 | |||
586 | /* From section 5.4.2 of the GLSL 1.20 spec: |
||
587 | * "If a matrix is constructed from a matrix, then each component |
||
588 | * (column i, row j) in the result that has a corresponding component |
||
589 | * (column i, row j) in the argument will be initialized from there." |
||
590 | */ |
||
591 | unsigned cols = MIN2(type->matrix_columns, value->type->matrix_columns); |
||
592 | unsigned rows = MIN2(type->vector_elements, value->type->vector_elements); |
||
593 | for (unsigned i = 0; i < cols; i++) { |
||
594 | for (unsigned j = 0; j < rows; j++) { |
||
595 | const unsigned src = i * value->type->vector_elements + j; |
||
596 | const unsigned dst = i * type->vector_elements + j; |
||
597 | this->value.f[dst] = value->value.f[src]; |
||
598 | } |
||
599 | } |
||
600 | |||
601 | /* "All other components will be initialized to the identity matrix." */ |
||
602 | for (unsigned i = cols; i < type->matrix_columns; i++) |
||
603 | this->value.f[i * type->vector_elements + i] = 1.0; |
||
604 | |||
605 | return; |
||
606 | } |
||
607 | |||
608 | /* Use each component from each entry in the value_list to initialize one |
||
609 | * component of the constant being constructed. |
||
610 | */ |
||
611 | for (unsigned i = 0; i < type->components(); /* empty */) { |
||
612 | assert(value->as_constant() != NULL); |
||
613 | assert(!value->is_tail_sentinel()); |
||
614 | |||
615 | for (unsigned j = 0; j < value->type->components(); j++) { |
||
616 | switch (type->base_type) { |
||
617 | case GLSL_TYPE_UINT: |
||
618 | this->value.u[i] = value->get_uint_component(j); |
||
619 | break; |
||
620 | case GLSL_TYPE_INT: |
||
621 | this->value.i[i] = value->get_int_component(j); |
||
622 | break; |
||
623 | case GLSL_TYPE_FLOAT: |
||
624 | this->value.f[i] = value->get_float_component(j); |
||
625 | break; |
||
626 | case GLSL_TYPE_BOOL: |
||
627 | this->value.b[i] = value->get_bool_component(j); |
||
628 | break; |
||
629 | default: |
||
630 | /* FINISHME: What to do? Exceptions are not the answer. |
||
631 | */ |
||
632 | break; |
||
633 | } |
||
634 | |||
635 | i++; |
||
636 | if (i >= type->components()) |
||
637 | break; |
||
638 | } |
||
639 | |||
640 | value = (ir_constant *) value->next; |
||
641 | } |
||
642 | } |
||
643 | |||
644 | ir_constant * |
||
645 | ir_constant::zero(void *mem_ctx, const glsl_type *type) |
||
646 | { |
||
647 | assert(type->is_numeric() || type->is_boolean()); |
||
648 | |||
649 | ir_constant *c = new(mem_ctx) ir_constant; |
||
650 | c->type = type; |
||
651 | memset(&c->value, 0, sizeof(c->value)); |
||
652 | |||
653 | return c; |
||
654 | } |
||
655 | |||
656 | bool |
||
657 | ir_constant::get_bool_component(unsigned i) const |
||
658 | { |
||
659 | switch (this->type->base_type) { |
||
660 | case GLSL_TYPE_UINT: return this->value.u[i] != 0; |
||
661 | case GLSL_TYPE_INT: return this->value.i[i] != 0; |
||
662 | case GLSL_TYPE_FLOAT: return ((int)this->value.f[i]) != 0; |
||
663 | case GLSL_TYPE_BOOL: return this->value.b[i]; |
||
664 | default: assert(!"Should not get here."); break; |
||
665 | } |
||
666 | |||
667 | /* Must return something to make the compiler happy. This is clearly an |
||
668 | * error case. |
||
669 | */ |
||
670 | return false; |
||
671 | } |
||
672 | |||
673 | float |
||
674 | ir_constant::get_float_component(unsigned i) const |
||
675 | { |
||
676 | switch (this->type->base_type) { |
||
677 | case GLSL_TYPE_UINT: return (float) this->value.u[i]; |
||
678 | case GLSL_TYPE_INT: return (float) this->value.i[i]; |
||
679 | case GLSL_TYPE_FLOAT: return this->value.f[i]; |
||
680 | case GLSL_TYPE_BOOL: return this->value.b[i] ? 1.0 : 0.0; |
||
681 | default: assert(!"Should not get here."); break; |
||
682 | } |
||
683 | |||
684 | /* Must return something to make the compiler happy. This is clearly an |
||
685 | * error case. |
||
686 | */ |
||
687 | return 0.0; |
||
688 | } |
||
689 | |||
690 | int |
||
691 | ir_constant::get_int_component(unsigned i) const |
||
692 | { |
||
693 | switch (this->type->base_type) { |
||
694 | case GLSL_TYPE_UINT: return this->value.u[i]; |
||
695 | case GLSL_TYPE_INT: return this->value.i[i]; |
||
696 | case GLSL_TYPE_FLOAT: return (int) this->value.f[i]; |
||
697 | case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; |
||
698 | default: assert(!"Should not get here."); break; |
||
699 | } |
||
700 | |||
701 | /* Must return something to make the compiler happy. This is clearly an |
||
702 | * error case. |
||
703 | */ |
||
704 | return 0; |
||
705 | } |
||
706 | |||
707 | unsigned |
||
708 | ir_constant::get_uint_component(unsigned i) const |
||
709 | { |
||
710 | switch (this->type->base_type) { |
||
711 | case GLSL_TYPE_UINT: return this->value.u[i]; |
||
712 | case GLSL_TYPE_INT: return this->value.i[i]; |
||
713 | case GLSL_TYPE_FLOAT: return (unsigned) this->value.f[i]; |
||
714 | case GLSL_TYPE_BOOL: return this->value.b[i] ? 1 : 0; |
||
715 | default: assert(!"Should not get here."); break; |
||
716 | } |
||
717 | |||
718 | /* Must return something to make the compiler happy. This is clearly an |
||
719 | * error case. |
||
720 | */ |
||
721 | return 0; |
||
722 | } |
||
723 | |||
724 | ir_constant * |
||
725 | ir_constant::get_array_element(unsigned i) const |
||
726 | { |
||
727 | assert(this->type->is_array()); |
||
728 | |||
729 | /* From page 35 (page 41 of the PDF) of the GLSL 1.20 spec: |
||
730 | * |
||
731 | * "Behavior is undefined if a shader subscripts an array with an index |
||
732 | * less than 0 or greater than or equal to the size the array was |
||
733 | * declared with." |
||
734 | * |
||
735 | * Most out-of-bounds accesses are removed before things could get this far. |
||
736 | * There are cases where non-constant array index values can get constant |
||
737 | * folded. |
||
738 | */ |
||
739 | if (int(i) < 0) |
||
740 | i = 0; |
||
741 | else if (i >= this->type->length) |
||
742 | i = this->type->length - 1; |
||
743 | |||
744 | return array_elements[i]; |
||
745 | } |
||
746 | |||
747 | ir_constant * |
||
748 | ir_constant::get_record_field(const char *name) |
||
749 | { |
||
750 | int idx = this->type->field_index(name); |
||
751 | |||
752 | if (idx < 0) |
||
753 | return NULL; |
||
754 | |||
755 | if (this->components.is_empty()) |
||
756 | return NULL; |
||
757 | |||
758 | exec_node *node = this->components.head; |
||
759 | for (int i = 0; i < idx; i++) { |
||
760 | node = node->next; |
||
761 | |||
762 | /* If the end of the list is encountered before the element matching the |
||
763 | * requested field is found, return NULL. |
||
764 | */ |
||
765 | if (node->is_tail_sentinel()) |
||
766 | return NULL; |
||
767 | } |
||
768 | |||
769 | return (ir_constant *) node; |
||
770 | } |
||
771 | |||
772 | |||
773 | bool |
||
774 | ir_constant::has_value(const ir_constant *c) const |
||
775 | { |
||
776 | if (this->type != c->type) |
||
777 | return false; |
||
778 | |||
779 | if (this->type->is_array()) { |
||
780 | for (unsigned i = 0; i < this->type->length; i++) { |
||
781 | if (!this->array_elements[i]->has_value(c->array_elements[i])) |
||
782 | return false; |
||
783 | } |
||
784 | return true; |
||
785 | } |
||
786 | |||
787 | if (this->type->base_type == GLSL_TYPE_STRUCT) { |
||
788 | const exec_node *a_node = this->components.head; |
||
789 | const exec_node *b_node = c->components.head; |
||
790 | |||
791 | while (!a_node->is_tail_sentinel()) { |
||
792 | assert(!b_node->is_tail_sentinel()); |
||
793 | |||
794 | const ir_constant *const a_field = (ir_constant *) a_node; |
||
795 | const ir_constant *const b_field = (ir_constant *) b_node; |
||
796 | |||
797 | if (!a_field->has_value(b_field)) |
||
798 | return false; |
||
799 | |||
800 | a_node = a_node->next; |
||
801 | b_node = b_node->next; |
||
802 | } |
||
803 | |||
804 | return true; |
||
805 | } |
||
806 | |||
807 | for (unsigned i = 0; i < this->type->components(); i++) { |
||
808 | switch (this->type->base_type) { |
||
809 | case GLSL_TYPE_UINT: |
||
810 | if (this->value.u[i] != c->value.u[i]) |
||
811 | return false; |
||
812 | break; |
||
813 | case GLSL_TYPE_INT: |
||
814 | if (this->value.i[i] != c->value.i[i]) |
||
815 | return false; |
||
816 | break; |
||
817 | case GLSL_TYPE_FLOAT: |
||
818 | if (this->value.f[i] != c->value.f[i]) |
||
819 | return false; |
||
820 | break; |
||
821 | case GLSL_TYPE_BOOL: |
||
822 | if (this->value.b[i] != c->value.b[i]) |
||
823 | return false; |
||
824 | break; |
||
825 | default: |
||
826 | assert(!"Should not get here."); |
||
827 | return false; |
||
828 | } |
||
829 | } |
||
830 | |||
831 | return true; |
||
832 | } |
||
833 | |||
834 | bool |
||
835 | ir_constant::is_zero() const |
||
836 | { |
||
837 | if (!this->type->is_scalar() && !this->type->is_vector()) |
||
838 | return false; |
||
839 | |||
840 | for (unsigned c = 0; c < this->type->vector_elements; c++) { |
||
841 | switch (this->type->base_type) { |
||
842 | case GLSL_TYPE_FLOAT: |
||
843 | if (this->value.f[c] != 0.0) |
||
844 | return false; |
||
845 | break; |
||
846 | case GLSL_TYPE_INT: |
||
847 | if (this->value.i[c] != 0) |
||
848 | return false; |
||
849 | break; |
||
850 | case GLSL_TYPE_UINT: |
||
851 | if (this->value.u[c] != 0) |
||
852 | return false; |
||
853 | break; |
||
854 | case GLSL_TYPE_BOOL: |
||
855 | if (this->value.b[c] != false) |
||
856 | return false; |
||
857 | break; |
||
858 | default: |
||
859 | /* The only other base types are structures, arrays, and samplers. |
||
860 | * Samplers cannot be constants, and the others should have been |
||
861 | * filtered out above. |
||
862 | */ |
||
863 | assert(!"Should not get here."); |
||
864 | return false; |
||
865 | } |
||
866 | } |
||
867 | |||
868 | return true; |
||
869 | } |
||
870 | |||
871 | bool |
||
872 | ir_constant::is_one() const |
||
873 | { |
||
874 | if (!this->type->is_scalar() && !this->type->is_vector()) |
||
875 | return false; |
||
876 | |||
877 | for (unsigned c = 0; c < this->type->vector_elements; c++) { |
||
878 | switch (this->type->base_type) { |
||
879 | case GLSL_TYPE_FLOAT: |
||
880 | if (this->value.f[c] != 1.0) |
||
881 | return false; |
||
882 | break; |
||
883 | case GLSL_TYPE_INT: |
||
884 | if (this->value.i[c] != 1) |
||
885 | return false; |
||
886 | break; |
||
887 | case GLSL_TYPE_UINT: |
||
888 | if (this->value.u[c] != 1) |
||
889 | return false; |
||
890 | break; |
||
891 | case GLSL_TYPE_BOOL: |
||
892 | if (this->value.b[c] != true) |
||
893 | return false; |
||
894 | break; |
||
895 | default: |
||
896 | /* The only other base types are structures, arrays, and samplers. |
||
897 | * Samplers cannot be constants, and the others should have been |
||
898 | * filtered out above. |
||
899 | */ |
||
900 | assert(!"Should not get here."); |
||
901 | return false; |
||
902 | } |
||
903 | } |
||
904 | |||
905 | return true; |
||
906 | } |
||
907 | |||
908 | bool |
||
909 | ir_constant::is_negative_one() const |
||
910 | { |
||
911 | if (!this->type->is_scalar() && !this->type->is_vector()) |
||
912 | return false; |
||
913 | |||
914 | if (this->type->is_boolean()) |
||
915 | return false; |
||
916 | |||
917 | for (unsigned c = 0; c < this->type->vector_elements; c++) { |
||
918 | switch (this->type->base_type) { |
||
919 | case GLSL_TYPE_FLOAT: |
||
920 | if (this->value.f[c] != -1.0) |
||
921 | return false; |
||
922 | break; |
||
923 | case GLSL_TYPE_INT: |
||
924 | if (this->value.i[c] != -1) |
||
925 | return false; |
||
926 | break; |
||
927 | case GLSL_TYPE_UINT: |
||
928 | if (int(this->value.u[c]) != -1) |
||
929 | return false; |
||
930 | break; |
||
931 | default: |
||
932 | /* The only other base types are structures, arrays, samplers, and |
||
933 | * booleans. Samplers cannot be constants, and the others should |
||
934 | * have been filtered out above. |
||
935 | */ |
||
936 | assert(!"Should not get here."); |
||
937 | return false; |
||
938 | } |
||
939 | } |
||
940 | |||
941 | return true; |
||
942 | } |
||
943 | |||
944 | ir_loop::ir_loop() |
||
945 | { |
||
946 | this->ir_type = ir_type_loop; |
||
947 | this->cmp = ir_unop_neg; |
||
948 | this->from = NULL; |
||
949 | this->to = NULL; |
||
950 | this->increment = NULL; |
||
951 | this->counter = NULL; |
||
952 | } |
||
953 | |||
954 | |||
955 | ir_dereference_variable::ir_dereference_variable(ir_variable *var) |
||
956 | { |
||
957 | this->ir_type = ir_type_dereference_variable; |
||
958 | this->var = var; |
||
959 | this->type = (var != NULL) ? var->type : glsl_type::error_type; |
||
960 | } |
||
961 | |||
962 | |||
963 | ir_dereference_array::ir_dereference_array(ir_rvalue *value, |
||
964 | ir_rvalue *array_index) |
||
965 | { |
||
966 | this->ir_type = ir_type_dereference_array; |
||
967 | this->array_index = array_index; |
||
968 | this->set_array(value); |
||
969 | } |
||
970 | |||
971 | |||
972 | ir_dereference_array::ir_dereference_array(ir_variable *var, |
||
973 | ir_rvalue *array_index) |
||
974 | { |
||
975 | void *ctx = ralloc_parent(var); |
||
976 | |||
977 | this->ir_type = ir_type_dereference_array; |
||
978 | this->array_index = array_index; |
||
979 | this->set_array(new(ctx) ir_dereference_variable(var)); |
||
980 | } |
||
981 | |||
982 | |||
983 | void |
||
984 | ir_dereference_array::set_array(ir_rvalue *value) |
||
985 | { |
||
986 | this->array = value; |
||
987 | this->type = glsl_type::error_type; |
||
988 | |||
989 | if (this->array != NULL) { |
||
990 | const glsl_type *const vt = this->array->type; |
||
991 | |||
992 | if (vt->is_array()) { |
||
993 | type = vt->element_type(); |
||
994 | } else if (vt->is_matrix()) { |
||
995 | type = vt->column_type(); |
||
996 | } else if (vt->is_vector()) { |
||
997 | type = vt->get_base_type(); |
||
998 | } |
||
999 | } |
||
1000 | } |
||
1001 | |||
1002 | |||
1003 | ir_dereference_record::ir_dereference_record(ir_rvalue *value, |
||
1004 | const char *field) |
||
1005 | { |
||
1006 | this->ir_type = ir_type_dereference_record; |
||
1007 | this->record = value; |
||
1008 | this->field = ralloc_strdup(this, field); |
||
1009 | this->type = (this->record != NULL) |
||
1010 | ? this->record->type->field_type(field) : glsl_type::error_type; |
||
1011 | } |
||
1012 | |||
1013 | |||
1014 | ir_dereference_record::ir_dereference_record(ir_variable *var, |
||
1015 | const char *field) |
||
1016 | { |
||
1017 | void *ctx = ralloc_parent(var); |
||
1018 | |||
1019 | this->ir_type = ir_type_dereference_record; |
||
1020 | this->record = new(ctx) ir_dereference_variable(var); |
||
1021 | this->field = ralloc_strdup(this, field); |
||
1022 | this->type = (this->record != NULL) |
||
1023 | ? this->record->type->field_type(field) : glsl_type::error_type; |
||
1024 | } |
||
1025 | |||
1026 | bool type_contains_sampler(const glsl_type *type) |
||
1027 | { |
||
1028 | if (type->is_array()) { |
||
1029 | return type_contains_sampler(type->fields.array); |
||
1030 | } else if (type->is_record()) { |
||
1031 | for (unsigned int i = 0; i < type->length; i++) { |
||
1032 | if (type_contains_sampler(type->fields.structure[i].type)) |
||
1033 | return true; |
||
1034 | } |
||
1035 | return false; |
||
1036 | } else { |
||
1037 | return type->is_sampler(); |
||
1038 | } |
||
1039 | } |
||
1040 | |||
1041 | bool |
||
1042 | ir_dereference::is_lvalue() |
||
1043 | { |
||
1044 | ir_variable *var = this->variable_referenced(); |
||
1045 | |||
1046 | /* Every l-value derference chain eventually ends in a variable. |
||
1047 | */ |
||
1048 | if ((var == NULL) || var->read_only) |
||
1049 | return false; |
||
1050 | |||
1051 | if (this->type->is_array() && !var->array_lvalue) |
||
1052 | return false; |
||
1053 | |||
1054 | /* From page 17 (page 23 of the PDF) of the GLSL 1.20 spec: |
||
1055 | * |
||
1056 | * "Samplers cannot be treated as l-values; hence cannot be used |
||
1057 | * as out or inout function parameters, nor can they be |
||
1058 | * assigned into." |
||
1059 | */ |
||
1060 | if (type_contains_sampler(this->type)) |
||
1061 | return false; |
||
1062 | |||
1063 | return true; |
||
1064 | } |
||
1065 | |||
1066 | |||
1067 | const char *tex_opcode_strs[] = { "tex", "txb", "txl", "txd", "txf" }; |
||
1068 | |||
1069 | const char *ir_texture::opcode_string() |
||
1070 | { |
||
1071 | assert((unsigned int) op <= |
||
1072 | sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0])); |
||
1073 | return tex_opcode_strs[op]; |
||
1074 | } |
||
1075 | |||
1076 | ir_texture_opcode |
||
1077 | ir_texture::get_opcode(const char *str) |
||
1078 | { |
||
1079 | const int count = sizeof(tex_opcode_strs) / sizeof(tex_opcode_strs[0]); |
||
1080 | for (int op = 0; op < count; op++) { |
||
1081 | if (strcmp(str, tex_opcode_strs[op]) == 0) |
||
1082 | return (ir_texture_opcode) op; |
||
1083 | } |
||
1084 | return (ir_texture_opcode) -1; |
||
1085 | } |
||
1086 | |||
1087 | |||
1088 | void |
||
1089 | ir_texture::set_sampler(ir_dereference *sampler) |
||
1090 | { |
||
1091 | assert(sampler != NULL); |
||
1092 | this->sampler = sampler; |
||
1093 | |||
1094 | switch (sampler->type->sampler_type) { |
||
1095 | case GLSL_TYPE_FLOAT: |
||
1096 | this->type = glsl_type::vec4_type; |
||
1097 | break; |
||
1098 | case GLSL_TYPE_INT: |
||
1099 | this->type = glsl_type::ivec4_type; |
||
1100 | break; |
||
1101 | case GLSL_TYPE_UINT: |
||
1102 | this->type = glsl_type::uvec4_type; |
||
1103 | break; |
||
1104 | } |
||
1105 | } |
||
1106 | |||
1107 | |||
1108 | void |
||
1109 | ir_swizzle::init_mask(const unsigned *comp, unsigned count) |
||
1110 | { |
||
1111 | assert((count >= 1) && (count <= 4)); |
||
1112 | |||
1113 | memset(&this->mask, 0, sizeof(this->mask)); |
||
1114 | this->mask.num_components = count; |
||
1115 | |||
1116 | unsigned dup_mask = 0; |
||
1117 | switch (count) { |
||
1118 | case 4: |
||
1119 | assert(comp[3] <= 3); |
||
1120 | dup_mask |= (1U << comp[3]) |
||
1121 | & ((1U << comp[0]) | (1U << comp[1]) | (1U << comp[2])); |
||
1122 | this->mask.w = comp[3]; |
||
1123 | |||
1124 | case 3: |
||
1125 | assert(comp[2] <= 3); |
||
1126 | dup_mask |= (1U << comp[2]) |
||
1127 | & ((1U << comp[0]) | (1U << comp[1])); |
||
1128 | this->mask.z = comp[2]; |
||
1129 | |||
1130 | case 2: |
||
1131 | assert(comp[1] <= 3); |
||
1132 | dup_mask |= (1U << comp[1]) |
||
1133 | & ((1U << comp[0])); |
||
1134 | this->mask.y = comp[1]; |
||
1135 | |||
1136 | case 1: |
||
1137 | assert(comp[0] <= 3); |
||
1138 | this->mask.x = comp[0]; |
||
1139 | } |
||
1140 | |||
1141 | this->mask.has_duplicates = dup_mask != 0; |
||
1142 | |||
1143 | /* Based on the number of elements in the swizzle and the base type |
||
1144 | * (i.e., float, int, unsigned, or bool) of the vector being swizzled, |
||
1145 | * generate the type of the resulting value. |
||
1146 | */ |
||
1147 | type = glsl_type::get_instance(val->type->base_type, mask.num_components, 1); |
||
1148 | } |
||
1149 | |||
1150 | ir_swizzle::ir_swizzle(ir_rvalue *val, unsigned x, unsigned y, unsigned z, |
||
1151 | unsigned w, unsigned count) |
||
1152 | : val(val) |
||
1153 | { |
||
1154 | const unsigned components[4] = { x, y, z, w }; |
||
1155 | this->ir_type = ir_type_swizzle; |
||
1156 | this->init_mask(components, count); |
||
1157 | } |
||
1158 | |||
1159 | ir_swizzle::ir_swizzle(ir_rvalue *val, const unsigned *comp, |
||
1160 | unsigned count) |
||
1161 | : val(val) |
||
1162 | { |
||
1163 | this->ir_type = ir_type_swizzle; |
||
1164 | this->init_mask(comp, count); |
||
1165 | } |
||
1166 | |||
1167 | ir_swizzle::ir_swizzle(ir_rvalue *val, ir_swizzle_mask mask) |
||
1168 | { |
||
1169 | this->ir_type = ir_type_swizzle; |
||
1170 | this->val = val; |
||
1171 | this->mask = mask; |
||
1172 | this->type = glsl_type::get_instance(val->type->base_type, |
||
1173 | mask.num_components, 1); |
||
1174 | } |
||
1175 | |||
1176 | #define X 1 |
||
1177 | #define R 5 |
||
1178 | #define S 9 |
||
1179 | #define I 13 |
||
1180 | |||
1181 | ir_swizzle * |
||
1182 | ir_swizzle::create(ir_rvalue *val, const char *str, unsigned vector_length) |
||
1183 | { |
||
1184 | void *ctx = ralloc_parent(val); |
||
1185 | |||
1186 | /* For each possible swizzle character, this table encodes the value in |
||
1187 | * \c idx_map that represents the 0th element of the vector. For invalid |
||
1188 | * swizzle characters (e.g., 'k'), a special value is used that will allow |
||
1189 | * detection of errors. |
||
1190 | */ |
||
1191 | static const unsigned char base_idx[26] = { |
||
1192 | /* a b c d e f g h i j k l m */ |
||
1193 | R, R, I, I, I, I, R, I, I, I, I, I, I, |
||
1194 | /* n o p q r s t u v w x y z */ |
||
1195 | I, I, S, S, R, S, S, I, I, X, X, X, X |
||
1196 | }; |
||
1197 | |||
1198 | /* Each valid swizzle character has an entry in the previous table. This |
||
1199 | * table encodes the base index encoded in the previous table plus the actual |
||
1200 | * index of the swizzle character. When processing swizzles, the first |
||
1201 | * character in the string is indexed in the previous table. Each character |
||
1202 | * in the string is indexed in this table, and the value found there has the |
||
1203 | * value form the first table subtracted. The result must be on the range |
||
1204 | * [0,3]. |
||
1205 | * |
||
1206 | * For example, the string "wzyx" will get X from the first table. Each of |
||
1207 | * the charcaters will get X+3, X+2, X+1, and X+0 from this table. After |
||
1208 | * subtraction, the swizzle values are { 3, 2, 1, 0 }. |
||
1209 | * |
||
1210 | * The string "wzrg" will get X from the first table. Each of the characters |
||
1211 | * will get X+3, X+2, R+0, and R+1 from this table. After subtraction, the |
||
1212 | * swizzle values are { 3, 2, 4, 5 }. Since 4 and 5 are outside the range |
||
1213 | * [0,3], the error is detected. |
||
1214 | */ |
||
1215 | static const unsigned char idx_map[26] = { |
||
1216 | /* a b c d e f g h i j k l m */ |
||
1217 | R+3, R+2, 0, 0, 0, 0, R+1, 0, 0, 0, 0, 0, 0, |
||
1218 | /* n o p q r s t u v w x y z */ |
||
1219 | 0, 0, S+2, S+3, R+0, S+0, S+1, 0, 0, X+3, X+0, X+1, X+2 |
||
1220 | }; |
||
1221 | |||
1222 | int swiz_idx[4] = { 0, 0, 0, 0 }; |
||
1223 | unsigned i; |
||
1224 | |||
1225 | |||
1226 | /* Validate the first character in the swizzle string and look up the base |
||
1227 | * index value as described above. |
||
1228 | */ |
||
1229 | if ((str[0] < 'a') || (str[0] > 'z')) |
||
1230 | return NULL; |
||
1231 | |||
1232 | const unsigned base = base_idx[str[0] - 'a']; |
||
1233 | |||
1234 | |||
1235 | for (i = 0; (i < 4) && (str[i] != '\0'); i++) { |
||
1236 | /* Validate the next character, and, as described above, convert it to a |
||
1237 | * swizzle index. |
||
1238 | */ |
||
1239 | if ((str[i] < 'a') || (str[i] > 'z')) |
||
1240 | return NULL; |
||
1241 | |||
1242 | swiz_idx[i] = idx_map[str[i] - 'a'] - base; |
||
1243 | if ((swiz_idx[i] < 0) || (swiz_idx[i] >= (int) vector_length)) |
||
1244 | return NULL; |
||
1245 | } |
||
1246 | |||
1247 | if (str[i] != '\0') |
||
1248 | return NULL; |
||
1249 | |||
1250 | return new(ctx) ir_swizzle(val, swiz_idx[0], swiz_idx[1], swiz_idx[2], |
||
1251 | swiz_idx[3], i); |
||
1252 | } |
||
1253 | |||
1254 | #undef X |
||
1255 | #undef R |
||
1256 | #undef S |
||
1257 | #undef I |
||
1258 | |||
1259 | ir_variable * |
||
1260 | ir_swizzle::variable_referenced() |
||
1261 | { |
||
1262 | return this->val->variable_referenced(); |
||
1263 | } |
||
1264 | |||
1265 | |||
1266 | ir_variable::ir_variable(const struct glsl_type *type, const char *name, |
||
1267 | ir_variable_mode mode) |
||
1268 | : max_array_access(0), read_only(false), centroid(false), invariant(false), |
||
1269 | mode(mode), interpolation(ir_var_smooth), array_lvalue(false) |
||
1270 | { |
||
1271 | this->ir_type = ir_type_variable; |
||
1272 | this->type = type; |
||
1273 | this->name = ralloc_strdup(this, name); |
||
1274 | this->explicit_location = false; |
||
1275 | this->location = -1; |
||
1276 | this->warn_extension = NULL; |
||
1277 | this->constant_value = NULL; |
||
1278 | this->origin_upper_left = false; |
||
1279 | this->pixel_center_integer = false; |
||
1280 | this->used = false; |
||
1281 | |||
1282 | if (type && type->base_type == GLSL_TYPE_SAMPLER) |
||
1283 | this->read_only = true; |
||
1284 | } |
||
1285 | |||
1286 | |||
1287 | const char * |
||
1288 | ir_variable::interpolation_string() const |
||
1289 | { |
||
1290 | switch (this->interpolation) { |
||
1291 | case ir_var_smooth: return "smooth"; |
||
1292 | case ir_var_flat: return "flat"; |
||
1293 | case ir_var_noperspective: return "noperspective"; |
||
1294 | } |
||
1295 | |||
1296 | assert(!"Should not get here."); |
||
1297 | return ""; |
||
1298 | } |
||
1299 | |||
1300 | |||
1301 | unsigned |
||
1302 | ir_variable::component_slots() const |
||
1303 | { |
||
1304 | /* FINISHME: Sparsely accessed arrays require fewer slots. */ |
||
1305 | return this->type->component_slots(); |
||
1306 | } |
||
1307 | |||
1308 | |||
1309 | ir_function_signature::ir_function_signature(const glsl_type *return_type) |
||
1310 | : return_type(return_type), is_defined(false), _function(NULL) |
||
1311 | { |
||
1312 | this->ir_type = ir_type_function_signature; |
||
1313 | this->is_builtin = false; |
||
1314 | } |
||
1315 | |||
1316 | |||
1317 | const char * |
||
1318 | ir_function_signature::qualifiers_match(exec_list *params) |
||
1319 | { |
||
1320 | exec_list_iterator iter_a = parameters.iterator(); |
||
1321 | exec_list_iterator iter_b = params->iterator(); |
||
1322 | |||
1323 | /* check that the qualifiers match. */ |
||
1324 | while (iter_a.has_next()) { |
||
1325 | ir_variable *a = (ir_variable *)iter_a.get(); |
||
1326 | ir_variable *b = (ir_variable *)iter_b.get(); |
||
1327 | |||
1328 | if (a->read_only != b->read_only || |
||
1329 | a->mode != b->mode || |
||
1330 | a->interpolation != b->interpolation || |
||
1331 | a->centroid != b->centroid) { |
||
1332 | |||
1333 | /* parameter a's qualifiers don't match */ |
||
1334 | return a->name; |
||
1335 | } |
||
1336 | |||
1337 | iter_a.next(); |
||
1338 | iter_b.next(); |
||
1339 | } |
||
1340 | return NULL; |
||
1341 | } |
||
1342 | |||
1343 | |||
1344 | void |
||
1345 | ir_function_signature::replace_parameters(exec_list *new_params) |
||
1346 | { |
||
1347 | /* Destroy all of the previous parameter information. If the previous |
||
1348 | * parameter information comes from the function prototype, it may either |
||
1349 | * specify incorrect parameter names or not have names at all. |
||
1350 | */ |
||
1351 | foreach_iter(exec_list_iterator, iter, parameters) { |
||
1352 | assert(((ir_instruction *) iter.get())->as_variable() != NULL); |
||
1353 | |||
1354 | iter.remove(); |
||
1355 | } |
||
1356 | |||
1357 | new_params->move_nodes_to(¶meters); |
||
1358 | } |
||
1359 | |||
1360 | |||
1361 | ir_function::ir_function(const char *name) |
||
1362 | { |
||
1363 | this->ir_type = ir_type_function; |
||
1364 | this->name = ralloc_strdup(this, name); |
||
1365 | } |
||
1366 | |||
1367 | |||
1368 | bool |
||
1369 | ir_function::has_user_signature() |
||
1370 | { |
||
1371 | foreach_list(n, &this->signatures) { |
||
1372 | ir_function_signature *const sig = (ir_function_signature *) n; |
||
1373 | if (!sig->is_builtin) |
||
1374 | return true; |
||
1375 | } |
||
1376 | return false; |
||
1377 | } |
||
1378 | |||
1379 | |||
1380 | ir_call * |
||
1381 | ir_call::get_error_instruction(void *ctx) |
||
1382 | { |
||
1383 | ir_call *call = new(ctx) ir_call; |
||
1384 | |||
1385 | call->type = glsl_type::error_type; |
||
1386 | return call; |
||
1387 | } |
||
1388 | |||
1389 | void |
||
1390 | ir_call::set_callee(ir_function_signature *sig) |
||
1391 | { |
||
1392 | assert((this->type == NULL) || (this->type == sig->return_type)); |
||
1393 | |||
1394 | this->callee = sig; |
||
1395 | } |
||
1396 | |||
1397 | void |
||
1398 | visit_exec_list(exec_list *list, ir_visitor *visitor) |
||
1399 | { |
||
1400 | foreach_iter(exec_list_iterator, iter, *list) { |
||
1401 | ((ir_instruction *)iter.get())->accept(visitor); |
||
1402 | } |
||
1403 | } |
||
1404 | |||
1405 | |||
1406 | static void |
||
1407 | steal_memory(ir_instruction *ir, void *new_ctx) |
||
1408 | { |
||
1409 | ir_variable *var = ir->as_variable(); |
||
1410 | ir_constant *constant = ir->as_constant(); |
||
1411 | if (var != NULL && var->constant_value != NULL) |
||
1412 | steal_memory(var->constant_value, ir); |
||
1413 | |||
1414 | /* The components of aggregate constants are not visited by the normal |
||
1415 | * visitor, so steal their values by hand. |
||
1416 | */ |
||
1417 | if (constant != NULL) { |
||
1418 | if (constant->type->is_record()) { |
||
1419 | foreach_iter(exec_list_iterator, iter, constant->components) { |
||
1420 | ir_constant *field = (ir_constant *)iter.get(); |
||
1421 | steal_memory(field, ir); |
||
1422 | } |
||
1423 | } else if (constant->type->is_array()) { |
||
1424 | for (unsigned int i = 0; i < constant->type->length; i++) { |
||
1425 | steal_memory(constant->array_elements[i], ir); |
||
1426 | } |
||
1427 | } |
||
1428 | } |
||
1429 | |||
1430 | ralloc_steal(new_ctx, ir); |
||
1431 | } |
||
1432 | |||
1433 | |||
1434 | void |
||
1435 | reparent_ir(exec_list *list, void *mem_ctx) |
||
1436 | { |
||
1437 | foreach_list(node, list) { |
||
1438 | visit_tree((ir_instruction *) node, steal_memory, mem_ctx); |
||
1439 | } |
||
1440 | } |
||
1441 | |||
1442 | |||
1443 | static ir_rvalue * |
||
1444 | try_min_one(ir_rvalue *ir) |
||
1445 | { |
||
1446 | ir_expression *expr = ir->as_expression(); |
||
1447 | |||
1448 | if (!expr || expr->operation != ir_binop_min) |
||
1449 | return NULL; |
||
1450 | |||
1451 | if (expr->operands[0]->is_one()) |
||
1452 | return expr->operands[1]; |
||
1453 | |||
1454 | if (expr->operands[1]->is_one()) |
||
1455 | return expr->operands[0]; |
||
1456 | |||
1457 | return NULL; |
||
1458 | } |
||
1459 | |||
1460 | static ir_rvalue * |
||
1461 | try_max_zero(ir_rvalue *ir) |
||
1462 | { |
||
1463 | ir_expression *expr = ir->as_expression(); |
||
1464 | |||
1465 | if (!expr || expr->operation != ir_binop_max) |
||
1466 | return NULL; |
||
1467 | |||
1468 | if (expr->operands[0]->is_zero()) |
||
1469 | return expr->operands[1]; |
||
1470 | |||
1471 | if (expr->operands[1]->is_zero()) |
||
1472 | return expr->operands[0]; |
||
1473 | |||
1474 | return NULL; |
||
1475 | } |
||
1476 | |||
1477 | ir_rvalue * |
||
1478 | ir_rvalue::as_rvalue_to_saturate() |
||
1479 | { |
||
1480 | ir_expression *expr = this->as_expression(); |
||
1481 | |||
1482 | if (!expr) |
||
1483 | return NULL; |
||
1484 | |||
1485 | ir_rvalue *max_zero = try_max_zero(expr); |
||
1486 | if (max_zero) { |
||
1487 | return try_min_one(max_zero); |
||
1488 | } else { |
||
1489 | ir_rvalue *min_one = try_min_one(expr); |
||
1490 | if (min_one) { |
||
1491 | return try_max_zero(min_one); |
||
1492 | } |
||
1493 | } |
||
1494 | |||
1495 | return NULL; |
||
1496 | }>>>>>=>><>><>=>><>><>><>=>><>><>><>><>=>=>>= |