Use new memory pool allocator. Lots of debug code still in place...
[mesa.git] / src / mesa / shader / slang / slang_typeinfo.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /**
26 * \file slang_assemble_typeinfo.c
27 * slang type info
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_typeinfo.h"
33 #include "slang_compile.h"
34 #include "slang_log.h"
35 #include "slang_mem.h"
36 #include "prog_instruction.h"
37
38
39 /**
40 * Checks if a field selector is a general swizzle (an r-value swizzle
41 * with replicated components or an l-value swizzle mask) for a
42 * vector. Returns GL_TRUE if this is the case, <swz> is filled with
43 * swizzle information. Returns GL_FALSE otherwise.
44 */
45 GLboolean
46 _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
47 {
48 GLuint i;
49 GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
50
51 /* init to undefined.
52 * We rely on undefined/nil values to distinguish between
53 * regular swizzles and writemasks.
54 * For example, the swizzle ".xNNN" is the writemask ".x".
55 * That's different than the swizzle ".xxxx".
56 */
57 for (i = 0; i < 4; i++)
58 swz->swizzle[i] = SWIZZLE_NIL;
59
60 /* the swizzle can be at most 4-component long */
61 swz->num_components = slang_string_length(field);
62 if (swz->num_components > 4)
63 return GL_FALSE;
64
65 for (i = 0; i < swz->num_components; i++) {
66 /* mark which swizzle group is used */
67 switch (field[i]) {
68 case 'x':
69 case 'y':
70 case 'z':
71 case 'w':
72 xyzw = GL_TRUE;
73 break;
74 case 'r':
75 case 'g':
76 case 'b':
77 case 'a':
78 rgba = GL_TRUE;
79 break;
80 case 's':
81 case 't':
82 case 'p':
83 case 'q':
84 stpq = GL_TRUE;
85 break;
86 default:
87 return GL_FALSE;
88 }
89
90 /* collect swizzle component */
91 switch (field[i]) {
92 case 'x':
93 case 'r':
94 case 's':
95 swz->swizzle[i] = 0;
96 break;
97 case 'y':
98 case 'g':
99 case 't':
100 swz->swizzle[i] = 1;
101 break;
102 case 'z':
103 case 'b':
104 case 'p':
105 swz->swizzle[i] = 2;
106 break;
107 case 'w':
108 case 'a':
109 case 'q':
110 swz->swizzle[i] = 3;
111 break;
112 }
113
114 /* check if the component is valid for given vector's row count */
115 if (rows <= swz->swizzle[i])
116 return GL_FALSE;
117 }
118
119 /* only one swizzle group can be used */
120 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
121 return GL_FALSE;
122
123 return GL_TRUE;
124 }
125
126
127
128 /**
129 * Checks if a general swizzle is an l-value swizzle - these swizzles
130 * do not have duplicated fields. Returns GL_TRUE if this is a
131 * swizzle mask. Returns GL_FALSE otherwise
132 */
133 GLboolean
134 _slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
135 {
136 GLuint i, c = 0;
137
138 /* the swizzle may not be longer than the vector dim */
139 if (swz->num_components > rows)
140 return GL_FALSE;
141
142 /* the swizzle components cannot be duplicated */
143 for (i = 0; i < swz->num_components; i++) {
144 if ((c & (1 << swz->swizzle[i])) != 0)
145 return GL_FALSE;
146 c |= 1 << swz->swizzle[i];
147 }
148
149 return GL_TRUE;
150 }
151
152
153 /**
154 * Combines (multiplies) two swizzles to form single swizzle.
155 * Example: "vec.wzyx.yx" --> "vec.zw".
156 */
157 GLvoid
158 _slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
159 const slang_swizzle * right)
160 {
161 GLuint i;
162
163 dst->num_components = right->num_components;
164 for (i = 0; i < right->num_components; i++)
165 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
166 }
167
168
169 GLvoid
170 slang_type_specifier_ctr(slang_type_specifier * self)
171 {
172 self->type = SLANG_SPEC_VOID;
173 self->_struct = NULL;
174 self->_array = NULL;
175 }
176
177 GLvoid
178 slang_type_specifier_dtr(slang_type_specifier * self)
179 {
180 if (self->_struct != NULL) {
181 slang_struct_destruct(self->_struct);
182 #if USE_MEMPOOL
183 _slang_free(self->_struct);
184 #else
185 slang_alloc_free(self->_struct);
186 #endif
187 }
188 if (self->_array != NULL) {
189 slang_type_specifier_dtr(self->_array);
190 #if USE_MEMPOOL
191 _slang_free(self->_array);
192 #else
193 slang_alloc_free(self->_array);
194 #endif
195 }
196 }
197
198 GLboolean
199 slang_type_specifier_copy(slang_type_specifier * x,
200 const slang_type_specifier * y)
201 {
202 slang_type_specifier z;
203
204 slang_type_specifier_ctr(&z);
205 z.type = y->type;
206 if (z.type == SLANG_SPEC_STRUCT) {
207 #if USE_MEMPOOL
208 z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
209 #else
210 z._struct = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
211 #endif
212 if (z._struct == NULL) {
213 slang_type_specifier_dtr(&z);
214 return GL_FALSE;
215 }
216 if (!slang_struct_construct(z._struct)) {
217 #if USE_MEMPOOL
218 _slang_free(z._struct);
219 #else
220 slang_alloc_free(z._struct);
221 #endif
222 slang_type_specifier_dtr(&z);
223 return GL_FALSE;
224 }
225 if (!slang_struct_copy(z._struct, y->_struct)) {
226 slang_type_specifier_dtr(&z);
227 return GL_FALSE;
228 }
229 }
230 else if (z.type == SLANG_SPEC_ARRAY) {
231 z._array =
232 (slang_type_specifier *)
233 #if USE_MEMPOOL
234 _slang_alloc(sizeof(slang_type_specifier));
235 #else
236 slang_alloc_malloc(sizeof(slang_type_specifier));
237 #endif
238 if (z._array == NULL) {
239 slang_type_specifier_dtr(&z);
240 return GL_FALSE;
241 }
242 slang_type_specifier_ctr(z._array);
243 if (!slang_type_specifier_copy(z._array, y->_array)) {
244 slang_type_specifier_dtr(&z);
245 return GL_FALSE;
246 }
247 }
248 slang_type_specifier_dtr(x);
249 *x = z;
250 return GL_TRUE;
251 }
252
253
254 /**
255 * Test if two types are equal.
256 */
257 GLboolean
258 slang_type_specifier_equal(const slang_type_specifier * x,
259 const slang_type_specifier * y)
260 {
261 if (x->type != y->type)
262 return GL_FALSE;
263 if (x->type == SLANG_SPEC_STRUCT)
264 return slang_struct_equal(x->_struct, y->_struct);
265 if (x->type == SLANG_SPEC_ARRAY)
266 return slang_type_specifier_equal(x->_array, y->_array);
267 return GL_TRUE;
268 }
269
270
271 /**
272 * As above, but allow float/int casting.
273 */
274 static GLboolean
275 slang_type_specifier_compatible(const slang_type_specifier * x,
276 const slang_type_specifier * y)
277 {
278 /* special case: float == int */
279 if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
280 return GL_TRUE;
281 }
282 /* XXX may need to add bool/int compatibility, etc */
283
284 if (x->type != y->type)
285 return GL_FALSE;
286 if (x->type == SLANG_SPEC_STRUCT)
287 return slang_struct_equal(x->_struct, y->_struct);
288 if (x->type == SLANG_SPEC_ARRAY)
289 return slang_type_specifier_compatible(x->_array, y->_array);
290 return GL_TRUE;
291 }
292
293
294 GLboolean
295 slang_typeinfo_construct(slang_typeinfo * ti)
296 {
297 slang_type_specifier_ctr(&ti->spec);
298 ti->array_len = 0;
299 return GL_TRUE;
300 }
301
302 GLvoid
303 slang_typeinfo_destruct(slang_typeinfo * ti)
304 {
305 slang_type_specifier_dtr(&ti->spec);
306 }
307
308
309
310 /**
311 * Determine the return type of a function.
312 * \param a_name the function name
313 * \param param function parameters (overloading)
314 * \param num_params number of parameters to function
315 * \param space namespace to search
316 * \param spec returns the type
317 * \param funFound returns pointer to the function, or NULL if not found.
318 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
319 */
320 static GLboolean
321 _slang_typeof_function(slang_atom a_name,
322 slang_operation * params, GLuint num_params,
323 const slang_name_space * space,
324 slang_type_specifier * spec,
325 slang_function **funFound,
326 slang_atom_pool *atoms, slang_info_log *log)
327 {
328 *funFound = _slang_locate_function(space->funcs, a_name, params,
329 num_params, space, atoms, log);
330 if (!*funFound)
331 return GL_TRUE; /* yes, not false */
332 return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
333 }
334
335
336 /**
337 * Determine the type of a math function.
338 * \param name name of the operator, one of +,-,*,/ or unary -
339 * \param params array of function parameters
340 * \param num_params number of parameters
341 * \param space namespace to use
342 * \param spec returns the function's type
343 * \param atoms atom pool
344 * \return GL_TRUE for success, GL_FALSE if failure
345 */
346 static GLboolean
347 typeof_math_call(const char *name, slang_operation *call,
348 const slang_name_space * space,
349 slang_type_specifier * spec,
350 slang_atom_pool * atoms,
351 slang_info_log *log)
352 {
353 if (call->fun) {
354 /* we've previously resolved this function call */
355 slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
356 return GL_TRUE;
357 }
358 else {
359 slang_atom atom;
360 slang_function *fun;
361
362 /* number of params: */
363 assert(call->num_children == 1 || call->num_children == 2);
364
365 atom = slang_atom_pool_atom(atoms, name);
366 if (!_slang_typeof_function(atom, call->children, call->num_children,
367 space, spec, &fun, atoms, log))
368 return GL_FALSE;
369
370 if (fun) {
371 /* Save pointer to save time in future */
372 call->fun = fun;
373 return GL_TRUE;
374 }
375 return GL_FALSE;
376 }
377 }
378
379 GLboolean
380 _slang_typeof_operation(const slang_assemble_ctx * A,
381 slang_operation * op,
382 slang_typeinfo * ti)
383 {
384 return _slang_typeof_operation_(op, &A->space, ti, A->atoms, A->log);
385 }
386
387
388 /**
389 * Determine the return type of an operation.
390 * \param op the operation node
391 * \param space the namespace to use
392 * \param ti the returned type
393 * \param atoms atom pool
394 * \return GL_TRUE for success, GL_FALSE if failure
395 */
396 GLboolean
397 _slang_typeof_operation_(slang_operation * op,
398 const slang_name_space * space,
399 slang_typeinfo * ti,
400 slang_atom_pool * atoms,
401 slang_info_log *log)
402 {
403 ti->can_be_referenced = GL_FALSE;
404 ti->is_swizzled = GL_FALSE;
405
406 switch (op->type) {
407 case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
408 case SLANG_OPER_BLOCK_NEW_SCOPE:
409 case SLANG_OPER_VARIABLE_DECL:
410 case SLANG_OPER_ASM:
411 case SLANG_OPER_BREAK:
412 case SLANG_OPER_CONTINUE:
413 case SLANG_OPER_DISCARD:
414 case SLANG_OPER_RETURN:
415 case SLANG_OPER_IF:
416 case SLANG_OPER_WHILE:
417 case SLANG_OPER_DO:
418 case SLANG_OPER_FOR:
419 case SLANG_OPER_VOID:
420 ti->spec.type = SLANG_SPEC_VOID;
421 break;
422 case SLANG_OPER_EXPRESSION:
423 case SLANG_OPER_ASSIGN:
424 case SLANG_OPER_ADDASSIGN:
425 case SLANG_OPER_SUBASSIGN:
426 case SLANG_OPER_MULASSIGN:
427 case SLANG_OPER_DIVASSIGN:
428 case SLANG_OPER_PREINCREMENT:
429 case SLANG_OPER_PREDECREMENT:
430 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
431 return GL_FALSE;
432 break;
433 case SLANG_OPER_LITERAL_BOOL:
434 if (op->literal_size == 1)
435 ti->spec.type = SLANG_SPEC_BOOL;
436 else if (op->literal_size == 2)
437 ti->spec.type = SLANG_SPEC_BVEC2;
438 else if (op->literal_size == 3)
439 ti->spec.type = SLANG_SPEC_BVEC3;
440 else if (op->literal_size == 4)
441 ti->spec.type = SLANG_SPEC_BVEC4;
442 else {
443 _mesa_problem(NULL,
444 "Unexpected bool literal_size %d in _slang_typeof_operation()",
445 op->literal_size);
446 ti->spec.type = SLANG_SPEC_BOOL;
447 }
448 break;
449 case SLANG_OPER_LOGICALOR:
450 case SLANG_OPER_LOGICALXOR:
451 case SLANG_OPER_LOGICALAND:
452 case SLANG_OPER_EQUAL:
453 case SLANG_OPER_NOTEQUAL:
454 case SLANG_OPER_LESS:
455 case SLANG_OPER_GREATER:
456 case SLANG_OPER_LESSEQUAL:
457 case SLANG_OPER_GREATEREQUAL:
458 case SLANG_OPER_NOT:
459 ti->spec.type = SLANG_SPEC_BOOL;
460 break;
461 case SLANG_OPER_LITERAL_INT:
462 if (op->literal_size == 1)
463 ti->spec.type = SLANG_SPEC_INT;
464 else if (op->literal_size == 2)
465 ti->spec.type = SLANG_SPEC_IVEC2;
466 else if (op->literal_size == 3)
467 ti->spec.type = SLANG_SPEC_IVEC3;
468 else if (op->literal_size == 4)
469 ti->spec.type = SLANG_SPEC_IVEC4;
470 else {
471 _mesa_problem(NULL,
472 "Unexpected int literal_size %d in _slang_typeof_operation()",
473 op->literal_size);
474 ti->spec.type = SLANG_SPEC_INT;
475 }
476 break;
477 case SLANG_OPER_LITERAL_FLOAT:
478 if (op->literal_size == 1)
479 ti->spec.type = SLANG_SPEC_FLOAT;
480 else if (op->literal_size == 2)
481 ti->spec.type = SLANG_SPEC_VEC2;
482 else if (op->literal_size == 3)
483 ti->spec.type = SLANG_SPEC_VEC3;
484 else if (op->literal_size == 4)
485 ti->spec.type = SLANG_SPEC_VEC4;
486 else {
487 _mesa_problem(NULL,
488 "Unexpected float literal_size %d in _slang_typeof_operation()",
489 op->literal_size);
490 ti->spec.type = SLANG_SPEC_FLOAT;
491 }
492 break;
493 case SLANG_OPER_IDENTIFIER:
494 {
495 slang_variable *var;
496 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
497 if (!var) {
498 slang_info_log_error(log, "undefined variable '%s'",
499 (char *) op->a_id);
500 return GL_FALSE;
501 }
502 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
503 slang_info_log_memory(log);
504 return GL_FALSE;
505 }
506 ti->can_be_referenced = GL_TRUE;
507 ti->array_len = var->array_len;
508 }
509 break;
510 case SLANG_OPER_SEQUENCE:
511 /* TODO: check [0] and [1] if they match */
512 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
513 return GL_FALSE;
514 }
515 ti->can_be_referenced = GL_FALSE;
516 ti->is_swizzled = GL_FALSE;
517 break;
518 /*case SLANG_OPER_MODASSIGN: */
519 /*case SLANG_OPER_LSHASSIGN: */
520 /*case SLANG_OPER_RSHASSIGN: */
521 /*case SLANG_OPER_ORASSIGN: */
522 /*case SLANG_OPER_XORASSIGN: */
523 /*case SLANG_OPER_ANDASSIGN: */
524 case SLANG_OPER_SELECT:
525 /* TODO: check [1] and [2] if they match */
526 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
527 return GL_FALSE;
528 }
529 ti->can_be_referenced = GL_FALSE;
530 ti->is_swizzled = GL_FALSE;
531 break;
532 /*case SLANG_OPER_BITOR: */
533 /*case SLANG_OPER_BITXOR: */
534 /*case SLANG_OPER_BITAND: */
535 /*case SLANG_OPER_LSHIFT: */
536 /*case SLANG_OPER_RSHIFT: */
537 case SLANG_OPER_ADD:
538 assert(op->num_children == 2);
539 if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
540 return GL_FALSE;
541 break;
542 case SLANG_OPER_SUBTRACT:
543 assert(op->num_children == 2);
544 if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
545 return GL_FALSE;
546 break;
547 case SLANG_OPER_MULTIPLY:
548 assert(op->num_children == 2);
549 if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
550 return GL_FALSE;
551 break;
552 case SLANG_OPER_DIVIDE:
553 assert(op->num_children == 2);
554 if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
555 return GL_FALSE;
556 break;
557 /*case SLANG_OPER_MODULUS: */
558 case SLANG_OPER_PLUS:
559 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
560 return GL_FALSE;
561 ti->can_be_referenced = GL_FALSE;
562 ti->is_swizzled = GL_FALSE;
563 break;
564 case SLANG_OPER_MINUS:
565 assert(op->num_children == 1);
566 if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
567 return GL_FALSE;
568 break;
569 /*case SLANG_OPER_COMPLEMENT: */
570 case SLANG_OPER_SUBSCRIPT:
571 {
572 slang_typeinfo _ti;
573
574 if (!slang_typeinfo_construct(&_ti))
575 return GL_FALSE;
576 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
577 slang_typeinfo_destruct(&_ti);
578 return GL_FALSE;
579 }
580 ti->can_be_referenced = _ti.can_be_referenced;
581 if (_ti.spec.type == SLANG_SPEC_ARRAY) {
582 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
583 slang_typeinfo_destruct(&_ti);
584 return GL_FALSE;
585 }
586 }
587 else {
588 if (!_slang_type_is_vector(_ti.spec.type)
589 && !_slang_type_is_matrix(_ti.spec.type)) {
590 slang_typeinfo_destruct(&_ti);
591 slang_info_log_error(log, "cannot index a non-array type");
592 return GL_FALSE;
593 }
594 ti->spec.type = _slang_type_base(_ti.spec.type);
595 }
596 slang_typeinfo_destruct(&_ti);
597 }
598 break;
599 case SLANG_OPER_CALL:
600 if (op->fun) {
601 /* we've resolved this call before */
602 slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
603 }
604 else {
605 slang_function *fun;
606 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
607 space, &ti->spec, &fun, atoms, log))
608 return GL_FALSE;
609 if (fun) {
610 /* save result for future use */
611 op->fun = fun;
612 }
613 else {
614 slang_struct *s =
615 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
616 if (s) {
617 /* struct initializer */
618 ti->spec.type = SLANG_SPEC_STRUCT;
619 ti->spec._struct =
620 #if USE_MEMPOOL
621 (slang_struct *) _slang_alloc(sizeof(slang_struct));
622 #else
623 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
624 #endif
625 if (ti->spec._struct == NULL)
626 return GL_FALSE;
627 if (!slang_struct_construct(ti->spec._struct)) {
628 #if USE_MEMPOOL
629 _slang_free(ti->spec._struct);
630 #else
631 slang_alloc_free(ti->spec._struct);
632 #endif
633 ti->spec._struct = NULL;
634 return GL_FALSE;
635 }
636 if (!slang_struct_copy(ti->spec._struct, s))
637 return GL_FALSE;
638 }
639 else {
640 /* float, int, vec4, mat3, etc. constructor? */
641 const char *name;
642 slang_type_specifier_type type;
643
644 name = slang_atom_pool_id(atoms, op->a_id);
645 type = slang_type_specifier_type_from_string(name);
646 if (type == SLANG_SPEC_VOID) {
647 slang_info_log_error(log, "undefined function '%s'", name);
648 return GL_FALSE;
649 }
650 ti->spec.type = type;
651 }
652 }
653 }
654 break;
655 case SLANG_OPER_FIELD:
656 {
657 slang_typeinfo _ti;
658
659 if (!slang_typeinfo_construct(&_ti))
660 return GL_FALSE;
661 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
662 slang_typeinfo_destruct(&_ti);
663 return GL_FALSE;
664 }
665 if (_ti.spec.type == SLANG_SPEC_STRUCT) {
666 slang_variable *field;
667
668 field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
669 GL_FALSE);
670 if (field == NULL) {
671 slang_typeinfo_destruct(&_ti);
672 return GL_FALSE;
673 }
674 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
675 slang_typeinfo_destruct(&_ti);
676 return GL_FALSE;
677 }
678 ti->can_be_referenced = _ti.can_be_referenced;
679 }
680 else {
681 GLuint rows;
682 const char *swizzle;
683 slang_type_specifier_type base;
684
685 /* determine the swizzle of the field expression */
686 if (!_slang_type_is_vector(_ti.spec.type)) {
687 slang_typeinfo_destruct(&_ti);
688 slang_info_log_error(log, "Can't swizzle scalar expression");
689 return GL_FALSE;
690 }
691 rows = _slang_type_dim(_ti.spec.type);
692 swizzle = slang_atom_pool_id(atoms, op->a_id);
693 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
694 slang_typeinfo_destruct(&_ti);
695 slang_info_log_error(log, "bad swizzle '%s'", swizzle);
696 return GL_FALSE;
697 }
698 ti->is_swizzled = GL_TRUE;
699 ti->can_be_referenced = _ti.can_be_referenced
700 && _slang_is_swizzle_mask(&ti->swz, rows);
701 if (_ti.is_swizzled) {
702 slang_swizzle swz;
703
704 /* swizzle the swizzle */
705 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
706 ti->swz = swz;
707 }
708 base = _slang_type_base(_ti.spec.type);
709 switch (ti->swz.num_components) {
710 case 1:
711 ti->spec.type = base;
712 break;
713 case 2:
714 switch (base) {
715 case SLANG_SPEC_FLOAT:
716 ti->spec.type = SLANG_SPEC_VEC2;
717 break;
718 case SLANG_SPEC_INT:
719 ti->spec.type = SLANG_SPEC_IVEC2;
720 break;
721 case SLANG_SPEC_BOOL:
722 ti->spec.type = SLANG_SPEC_BVEC2;
723 break;
724 default:
725 break;
726 }
727 break;
728 case 3:
729 switch (base) {
730 case SLANG_SPEC_FLOAT:
731 ti->spec.type = SLANG_SPEC_VEC3;
732 break;
733 case SLANG_SPEC_INT:
734 ti->spec.type = SLANG_SPEC_IVEC3;
735 break;
736 case SLANG_SPEC_BOOL:
737 ti->spec.type = SLANG_SPEC_BVEC3;
738 break;
739 default:
740 break;
741 }
742 break;
743 case 4:
744 switch (base) {
745 case SLANG_SPEC_FLOAT:
746 ti->spec.type = SLANG_SPEC_VEC4;
747 break;
748 case SLANG_SPEC_INT:
749 ti->spec.type = SLANG_SPEC_IVEC4;
750 break;
751 case SLANG_SPEC_BOOL:
752 ti->spec.type = SLANG_SPEC_BVEC4;
753 break;
754 default:
755 break;
756 }
757 break;
758 default:
759 break;
760 }
761 }
762 slang_typeinfo_destruct(&_ti);
763 }
764 break;
765 case SLANG_OPER_POSTINCREMENT:
766 case SLANG_OPER_POSTDECREMENT:
767 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
768 return GL_FALSE;
769 ti->can_be_referenced = GL_FALSE;
770 ti->is_swizzled = GL_FALSE;
771 break;
772 default:
773 return GL_FALSE;
774 }
775
776 return GL_TRUE;
777 }
778
779
780 /**
781 * Lookup a function according to name and parameter count/types.
782 */
783 slang_function *
784 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
785 slang_operation * args, GLuint num_args,
786 const slang_name_space * space, slang_atom_pool * atoms,
787 slang_info_log *log)
788 {
789 GLuint i;
790
791 for (i = 0; i < funcs->num_functions; i++) {
792 slang_function *f = &funcs->functions[i];
793 const GLuint haveRetValue = _slang_function_has_return_value(f);
794 GLuint j;
795
796 if (a_name != f->header.a_name)
797 continue;
798 if (f->param_count - haveRetValue != num_args)
799 continue;
800
801 /* compare parameter / argument types */
802 for (j = 0; j < num_args; j++) {
803 slang_typeinfo ti;
804
805 if (!slang_typeinfo_construct(&ti))
806 return NULL;
807 if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) {
808 slang_typeinfo_destruct(&ti);
809 return NULL;
810 }
811 if (!slang_type_specifier_compatible(&ti.spec,
812 &f->parameters->variables[j]->type.specifier)) {
813 slang_typeinfo_destruct(&ti);
814 break;
815 }
816 slang_typeinfo_destruct(&ti);
817
818 /* "out" and "inout" formal parameter requires the actual
819 * parameter to be l-value.
820 */
821 if (!ti.can_be_referenced &&
822 (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
823 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT))
824 break;
825 }
826 if (j == num_args)
827 return f;
828 }
829 if (funcs->outer_scope != NULL)
830 return _slang_locate_function(funcs->outer_scope, a_name, args,
831 num_args, space, atoms, log);
832 return NULL;
833 }
834
835
836 /**
837 * Determine if a type is a matrix.
838 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
839 */
840 GLboolean
841 _slang_type_is_matrix(slang_type_specifier_type ty)
842 {
843 switch (ty) {
844 case SLANG_SPEC_MAT2:
845 case SLANG_SPEC_MAT3:
846 case SLANG_SPEC_MAT4:
847 case SLANG_SPEC_MAT23:
848 case SLANG_SPEC_MAT32:
849 case SLANG_SPEC_MAT24:
850 case SLANG_SPEC_MAT42:
851 case SLANG_SPEC_MAT34:
852 case SLANG_SPEC_MAT43:
853 return GL_TRUE;
854 default:
855 return GL_FALSE;
856 }
857 }
858
859
860 /**
861 * Determine if a type is a vector.
862 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
863 */
864 GLboolean
865 _slang_type_is_vector(slang_type_specifier_type ty)
866 {
867 switch (ty) {
868 case SLANG_SPEC_VEC2:
869 case SLANG_SPEC_VEC3:
870 case SLANG_SPEC_VEC4:
871 case SLANG_SPEC_IVEC2:
872 case SLANG_SPEC_IVEC3:
873 case SLANG_SPEC_IVEC4:
874 case SLANG_SPEC_BVEC2:
875 case SLANG_SPEC_BVEC3:
876 case SLANG_SPEC_BVEC4:
877 return GL_TRUE;
878 default:
879 return GL_FALSE;
880 }
881 }
882
883
884 /**
885 * Given a vector type, return the type of the vector's elements.
886 * For a matrix, return the type of the columns.
887 */
888 slang_type_specifier_type
889 _slang_type_base(slang_type_specifier_type ty)
890 {
891 switch (ty) {
892 case SLANG_SPEC_FLOAT:
893 case SLANG_SPEC_VEC2:
894 case SLANG_SPEC_VEC3:
895 case SLANG_SPEC_VEC4:
896 return SLANG_SPEC_FLOAT;
897 case SLANG_SPEC_INT:
898 case SLANG_SPEC_IVEC2:
899 case SLANG_SPEC_IVEC3:
900 case SLANG_SPEC_IVEC4:
901 return SLANG_SPEC_INT;
902 case SLANG_SPEC_BOOL:
903 case SLANG_SPEC_BVEC2:
904 case SLANG_SPEC_BVEC3:
905 case SLANG_SPEC_BVEC4:
906 return SLANG_SPEC_BOOL;
907 case SLANG_SPEC_MAT2:
908 return SLANG_SPEC_VEC2;
909 case SLANG_SPEC_MAT3:
910 return SLANG_SPEC_VEC3;
911 case SLANG_SPEC_MAT4:
912 return SLANG_SPEC_VEC4;
913 case SLANG_SPEC_MAT23:
914 return SLANG_SPEC_VEC3;
915 case SLANG_SPEC_MAT32:
916 return SLANG_SPEC_VEC2;
917 case SLANG_SPEC_MAT24:
918 return SLANG_SPEC_VEC4;
919 case SLANG_SPEC_MAT42:
920 return SLANG_SPEC_VEC2;
921 case SLANG_SPEC_MAT34:
922 return SLANG_SPEC_VEC4;
923 case SLANG_SPEC_MAT43:
924 return SLANG_SPEC_VEC3;
925 default:
926 return SLANG_SPEC_VOID;
927 }
928 }
929
930
931 /**
932 * Return the dimensionality of a vector, or for a matrix, return number
933 * of columns.
934 */
935 GLuint
936 _slang_type_dim(slang_type_specifier_type ty)
937 {
938 switch (ty) {
939 case SLANG_SPEC_FLOAT:
940 case SLANG_SPEC_INT:
941 case SLANG_SPEC_BOOL:
942 return 1;
943 case SLANG_SPEC_VEC2:
944 case SLANG_SPEC_IVEC2:
945 case SLANG_SPEC_BVEC2:
946 case SLANG_SPEC_MAT2:
947 return 2;
948 case SLANG_SPEC_VEC3:
949 case SLANG_SPEC_IVEC3:
950 case SLANG_SPEC_BVEC3:
951 case SLANG_SPEC_MAT3:
952 return 3;
953 case SLANG_SPEC_VEC4:
954 case SLANG_SPEC_IVEC4:
955 case SLANG_SPEC_BVEC4:
956 case SLANG_SPEC_MAT4:
957 return 4;
958
959 case SLANG_SPEC_MAT23:
960 return 2;
961 case SLANG_SPEC_MAT32:
962 return 3;
963 case SLANG_SPEC_MAT24:
964 return 2;
965 case SLANG_SPEC_MAT42:
966 return 4;
967 case SLANG_SPEC_MAT34:
968 return 3;
969 case SLANG_SPEC_MAT43:
970 return 4;
971
972 default:
973 return 0;
974 }
975 }
976
977
978 /**
979 * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
980 */
981 GLenum
982 _slang_gltype_from_specifier(const slang_type_specifier *type)
983 {
984 switch (type->type) {
985 case SLANG_SPEC_BOOL:
986 return GL_BOOL;
987 case SLANG_SPEC_BVEC2:
988 return GL_BOOL_VEC2;
989 case SLANG_SPEC_BVEC3:
990 return GL_BOOL_VEC3;
991 case SLANG_SPEC_BVEC4:
992 return GL_BOOL_VEC4;
993 case SLANG_SPEC_INT:
994 return GL_INT;
995 case SLANG_SPEC_IVEC2:
996 return GL_INT_VEC2;
997 case SLANG_SPEC_IVEC3:
998 return GL_INT_VEC3;
999 case SLANG_SPEC_IVEC4:
1000 return GL_INT_VEC4;
1001 case SLANG_SPEC_FLOAT:
1002 return GL_FLOAT;
1003 case SLANG_SPEC_VEC2:
1004 return GL_FLOAT_VEC2;
1005 case SLANG_SPEC_VEC3:
1006 return GL_FLOAT_VEC3;
1007 case SLANG_SPEC_VEC4:
1008 return GL_FLOAT_VEC4;
1009 case SLANG_SPEC_MAT2:
1010 return GL_FLOAT_MAT2;
1011 case SLANG_SPEC_MAT3:
1012 return GL_FLOAT_MAT3;
1013 case SLANG_SPEC_MAT4:
1014 return GL_FLOAT_MAT4;
1015 case SLANG_SPEC_MAT23:
1016 return GL_FLOAT_MAT2x3;
1017 case SLANG_SPEC_MAT32:
1018 return GL_FLOAT_MAT3x2;
1019 case SLANG_SPEC_MAT24:
1020 return GL_FLOAT_MAT2x4;
1021 case SLANG_SPEC_MAT42:
1022 return GL_FLOAT_MAT4x2;
1023 case SLANG_SPEC_MAT34:
1024 return GL_FLOAT_MAT3x4;
1025 case SLANG_SPEC_MAT43:
1026 return GL_FLOAT_MAT4x3;
1027 case SLANG_SPEC_SAMPLER1D:
1028 return GL_SAMPLER_1D;
1029 case SLANG_SPEC_SAMPLER2D:
1030 return GL_SAMPLER_2D;
1031 case SLANG_SPEC_SAMPLER3D:
1032 return GL_SAMPLER_3D;
1033 case SLANG_SPEC_SAMPLERCUBE:
1034 return GL_SAMPLER_CUBE;
1035 case SLANG_SPEC_SAMPLER1DSHADOW:
1036 return GL_SAMPLER_1D_SHADOW;
1037 case SLANG_SPEC_SAMPLER2DSHADOW:
1038 return GL_SAMPLER_2D_SHADOW;
1039 case SLANG_SPEC_SAMPLER2DRECT:
1040 return GL_SAMPLER_2D_RECT_ARB;
1041 case SLANG_SPEC_SAMPLER2DRECTSHADOW:
1042 return GL_SAMPLER_2D_RECT_SHADOW_ARB;
1043 case SLANG_SPEC_ARRAY:
1044 return _slang_gltype_from_specifier(type->_array);
1045 case SLANG_SPEC_STRUCT:
1046 /* fall-through */
1047 default:
1048 return GL_NONE;
1049 }
1050 }
1051