mesa: added support for GLSL 1.20 array.length() method
[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 "main/imports.h"
32 #include "shader/prog_instruction.h"
33 #include "slang_typeinfo.h"
34 #include "slang_compile.h"
35 #include "slang_log.h"
36 #include "slang_mem.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 _slang_free(self->_struct);
183 }
184 if (self->_array != NULL) {
185 slang_type_specifier_dtr(self->_array);
186 _slang_free(self->_array);
187 }
188 }
189
190 GLboolean
191 slang_type_specifier_copy(slang_type_specifier * x,
192 const slang_type_specifier * y)
193 {
194 slang_type_specifier z;
195
196 slang_type_specifier_ctr(&z);
197 z.type = y->type;
198 if (z.type == SLANG_SPEC_STRUCT) {
199 z._struct = (slang_struct *) _slang_alloc(sizeof(slang_struct));
200 if (z._struct == NULL) {
201 slang_type_specifier_dtr(&z);
202 return GL_FALSE;
203 }
204 if (!slang_struct_construct(z._struct)) {
205 _slang_free(z._struct);
206 slang_type_specifier_dtr(&z);
207 return GL_FALSE;
208 }
209 if (!slang_struct_copy(z._struct, y->_struct)) {
210 slang_type_specifier_dtr(&z);
211 return GL_FALSE;
212 }
213 }
214 else if (z.type == SLANG_SPEC_ARRAY) {
215 z._array = (slang_type_specifier *)
216 _slang_alloc(sizeof(slang_type_specifier));
217 if (z._array == NULL) {
218 slang_type_specifier_dtr(&z);
219 return GL_FALSE;
220 }
221 slang_type_specifier_ctr(z._array);
222 if (!slang_type_specifier_copy(z._array, y->_array)) {
223 slang_type_specifier_dtr(&z);
224 return GL_FALSE;
225 }
226 }
227 slang_type_specifier_dtr(x);
228 *x = z;
229 return GL_TRUE;
230 }
231
232
233 /**
234 * Test if two types are equal.
235 */
236 GLboolean
237 slang_type_specifier_equal(const slang_type_specifier * x,
238 const slang_type_specifier * y)
239 {
240 if (x->type != y->type)
241 return GL_FALSE;
242 if (x->type == SLANG_SPEC_STRUCT)
243 return slang_struct_equal(x->_struct, y->_struct);
244 if (x->type == SLANG_SPEC_ARRAY)
245 return slang_type_specifier_equal(x->_array, y->_array);
246 return GL_TRUE;
247 }
248
249
250 /**
251 * As above, but allow float/int casting.
252 */
253 static GLboolean
254 slang_type_specifier_compatible(const slang_type_specifier * x,
255 const slang_type_specifier * y)
256 {
257 /* special case: float == int */
258 if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
259 return GL_TRUE;
260 }
261 /* XXX may need to add bool/int compatibility, etc */
262
263 if (x->type != y->type)
264 return GL_FALSE;
265 if (x->type == SLANG_SPEC_STRUCT)
266 return slang_struct_equal(x->_struct, y->_struct);
267 if (x->type == SLANG_SPEC_ARRAY)
268 return slang_type_specifier_compatible(x->_array, y->_array);
269 return GL_TRUE;
270 }
271
272
273 GLboolean
274 slang_typeinfo_construct(slang_typeinfo * ti)
275 {
276 _mesa_bzero(ti, sizeof(*ti));
277 slang_type_specifier_ctr(&ti->spec);
278 ti->array_len = 0;
279 return GL_TRUE;
280 }
281
282 GLvoid
283 slang_typeinfo_destruct(slang_typeinfo * ti)
284 {
285 slang_type_specifier_dtr(&ti->spec);
286 }
287
288
289
290 /**
291 * Determine the return type of a function.
292 * \param a_name the function name
293 * \param param function parameters (overloading)
294 * \param num_params number of parameters to function
295 * \param space namespace to search
296 * \param spec returns the type
297 * \param funFound returns pointer to the function, or NULL if not found.
298 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
299 */
300 static GLboolean
301 _slang_typeof_function(slang_atom a_name,
302 slang_operation * params, GLuint num_params,
303 const slang_name_space * space,
304 slang_type_specifier * spec,
305 slang_function **funFound,
306 slang_atom_pool *atoms, slang_info_log *log)
307 {
308 GLboolean error;
309
310 *funFound = _slang_locate_function(space->funcs, a_name, params,
311 num_params, space, atoms, log, &error);
312 if (error)
313 return GL_FALSE;
314
315 if (!*funFound)
316 return GL_TRUE; /* yes, not false */
317
318 return slang_type_specifier_copy(spec, &(*funFound)->header.type.specifier);
319 }
320
321
322 /**
323 * Determine the type of a math function.
324 * \param name name of the operator, one of +,-,*,/ or unary -
325 * \param params array of function parameters
326 * \param num_params number of parameters
327 * \param space namespace to use
328 * \param spec returns the function's type
329 * \param atoms atom pool
330 * \return GL_TRUE for success, GL_FALSE if failure
331 */
332 static GLboolean
333 typeof_math_call(const char *name, slang_operation *call,
334 const slang_name_space * space,
335 slang_type_specifier * spec,
336 slang_atom_pool * atoms,
337 slang_info_log *log)
338 {
339 if (call->fun) {
340 /* we've previously resolved this function call */
341 slang_type_specifier_copy(spec, &call->fun->header.type.specifier);
342 return GL_TRUE;
343 }
344 else {
345 slang_atom atom;
346 slang_function *fun;
347
348 /* number of params: */
349 assert(call->num_children == 1 || call->num_children == 2);
350
351 atom = slang_atom_pool_atom(atoms, name);
352 if (!_slang_typeof_function(atom, call->children, call->num_children,
353 space, spec, &fun, atoms, log))
354 return GL_FALSE;
355
356 if (fun) {
357 /* Save pointer to save time in future */
358 call->fun = fun;
359 return GL_TRUE;
360 }
361 return GL_FALSE;
362 }
363 }
364
365 GLboolean
366 _slang_typeof_operation(const slang_assemble_ctx * A,
367 slang_operation * op,
368 slang_typeinfo * ti)
369 {
370 return _slang_typeof_operation_(op, &A->space, ti, A->atoms, A->log);
371 }
372
373
374 /**
375 * Determine the return type of an operation.
376 * \param op the operation node
377 * \param space the namespace to use
378 * \param ti the returned type
379 * \param atoms atom pool
380 * \return GL_TRUE for success, GL_FALSE if failure
381 */
382 GLboolean
383 _slang_typeof_operation_(slang_operation * op,
384 const slang_name_space * space,
385 slang_typeinfo * ti,
386 slang_atom_pool * atoms,
387 slang_info_log *log)
388 {
389 ti->can_be_referenced = GL_FALSE;
390 ti->is_swizzled = GL_FALSE;
391
392 switch (op->type) {
393 case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
394 case SLANG_OPER_BLOCK_NEW_SCOPE:
395 case SLANG_OPER_ASM:
396 case SLANG_OPER_BREAK:
397 case SLANG_OPER_CONTINUE:
398 case SLANG_OPER_DISCARD:
399 case SLANG_OPER_RETURN:
400 case SLANG_OPER_IF:
401 case SLANG_OPER_WHILE:
402 case SLANG_OPER_DO:
403 case SLANG_OPER_FOR:
404 case SLANG_OPER_VOID:
405 ti->spec.type = SLANG_SPEC_VOID;
406 break;
407 case SLANG_OPER_EXPRESSION:
408 case SLANG_OPER_ASSIGN:
409 case SLANG_OPER_ADDASSIGN:
410 case SLANG_OPER_SUBASSIGN:
411 case SLANG_OPER_MULASSIGN:
412 case SLANG_OPER_DIVASSIGN:
413 case SLANG_OPER_PREINCREMENT:
414 case SLANG_OPER_PREDECREMENT:
415 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
416 return GL_FALSE;
417 break;
418 case SLANG_OPER_LITERAL_BOOL:
419 if (op->literal_size == 1)
420 ti->spec.type = SLANG_SPEC_BOOL;
421 else if (op->literal_size == 2)
422 ti->spec.type = SLANG_SPEC_BVEC2;
423 else if (op->literal_size == 3)
424 ti->spec.type = SLANG_SPEC_BVEC3;
425 else if (op->literal_size == 4)
426 ti->spec.type = SLANG_SPEC_BVEC4;
427 else {
428 _mesa_problem(NULL,
429 "Unexpected bool literal_size %d in _slang_typeof_operation()",
430 op->literal_size);
431 ti->spec.type = SLANG_SPEC_BOOL;
432 }
433 break;
434 case SLANG_OPER_LOGICALOR:
435 case SLANG_OPER_LOGICALXOR:
436 case SLANG_OPER_LOGICALAND:
437 case SLANG_OPER_EQUAL:
438 case SLANG_OPER_NOTEQUAL:
439 case SLANG_OPER_LESS:
440 case SLANG_OPER_GREATER:
441 case SLANG_OPER_LESSEQUAL:
442 case SLANG_OPER_GREATEREQUAL:
443 case SLANG_OPER_NOT:
444 ti->spec.type = SLANG_SPEC_BOOL;
445 break;
446 case SLANG_OPER_LITERAL_INT:
447 if (op->literal_size == 1)
448 ti->spec.type = SLANG_SPEC_INT;
449 else if (op->literal_size == 2)
450 ti->spec.type = SLANG_SPEC_IVEC2;
451 else if (op->literal_size == 3)
452 ti->spec.type = SLANG_SPEC_IVEC3;
453 else if (op->literal_size == 4)
454 ti->spec.type = SLANG_SPEC_IVEC4;
455 else {
456 _mesa_problem(NULL,
457 "Unexpected int literal_size %d in _slang_typeof_operation()",
458 op->literal_size);
459 ti->spec.type = SLANG_SPEC_INT;
460 }
461 break;
462 case SLANG_OPER_LITERAL_FLOAT:
463 if (op->literal_size == 1)
464 ti->spec.type = SLANG_SPEC_FLOAT;
465 else if (op->literal_size == 2)
466 ti->spec.type = SLANG_SPEC_VEC2;
467 else if (op->literal_size == 3)
468 ti->spec.type = SLANG_SPEC_VEC3;
469 else if (op->literal_size == 4)
470 ti->spec.type = SLANG_SPEC_VEC4;
471 else {
472 _mesa_problem(NULL,
473 "Unexpected float literal_size %d in _slang_typeof_operation()",
474 op->literal_size);
475 ti->spec.type = SLANG_SPEC_FLOAT;
476 }
477 break;
478 case SLANG_OPER_IDENTIFIER:
479 case SLANG_OPER_VARIABLE_DECL:
480 {
481 slang_variable *var;
482 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
483 if (!var) {
484 slang_info_log_error(log, "undefined variable '%s'",
485 (char *) op->a_id);
486 return GL_FALSE;
487 }
488 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
489 slang_info_log_memory(log);
490 return GL_FALSE;
491 }
492 ti->can_be_referenced = GL_TRUE;
493 ti->array_len = var->array_len;
494 }
495 break;
496 case SLANG_OPER_SEQUENCE:
497 /* TODO: check [0] and [1] if they match */
498 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
499 return GL_FALSE;
500 }
501 ti->can_be_referenced = GL_FALSE;
502 ti->is_swizzled = GL_FALSE;
503 break;
504 /*case SLANG_OPER_MODASSIGN: */
505 /*case SLANG_OPER_LSHASSIGN: */
506 /*case SLANG_OPER_RSHASSIGN: */
507 /*case SLANG_OPER_ORASSIGN: */
508 /*case SLANG_OPER_XORASSIGN: */
509 /*case SLANG_OPER_ANDASSIGN: */
510 case SLANG_OPER_SELECT:
511 /* TODO: check [1] and [2] 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_BITOR: */
519 /*case SLANG_OPER_BITXOR: */
520 /*case SLANG_OPER_BITAND: */
521 /*case SLANG_OPER_LSHIFT: */
522 /*case SLANG_OPER_RSHIFT: */
523 case SLANG_OPER_ADD:
524 assert(op->num_children == 2);
525 if (!typeof_math_call("+", op, space, &ti->spec, atoms, log))
526 return GL_FALSE;
527 break;
528 case SLANG_OPER_SUBTRACT:
529 assert(op->num_children == 2);
530 if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
531 return GL_FALSE;
532 break;
533 case SLANG_OPER_MULTIPLY:
534 assert(op->num_children == 2);
535 if (!typeof_math_call("*", op, space, &ti->spec, atoms, log))
536 return GL_FALSE;
537 break;
538 case SLANG_OPER_DIVIDE:
539 assert(op->num_children == 2);
540 if (!typeof_math_call("/", op, space, &ti->spec, atoms, log))
541 return GL_FALSE;
542 break;
543 /*case SLANG_OPER_MODULUS: */
544 case SLANG_OPER_PLUS:
545 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
546 return GL_FALSE;
547 ti->can_be_referenced = GL_FALSE;
548 ti->is_swizzled = GL_FALSE;
549 break;
550 case SLANG_OPER_MINUS:
551 assert(op->num_children == 1);
552 if (!typeof_math_call("-", op, space, &ti->spec, atoms, log))
553 return GL_FALSE;
554 break;
555 /*case SLANG_OPER_COMPLEMENT: */
556 case SLANG_OPER_SUBSCRIPT:
557 {
558 slang_typeinfo _ti;
559
560 if (!slang_typeinfo_construct(&_ti))
561 return GL_FALSE;
562 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
563 slang_typeinfo_destruct(&_ti);
564 return GL_FALSE;
565 }
566 ti->can_be_referenced = _ti.can_be_referenced;
567 if (_ti.spec.type == SLANG_SPEC_ARRAY) {
568 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
569 slang_typeinfo_destruct(&_ti);
570 return GL_FALSE;
571 }
572 }
573 else {
574 if (!_slang_type_is_vector(_ti.spec.type)
575 && !_slang_type_is_matrix(_ti.spec.type)) {
576 slang_typeinfo_destruct(&_ti);
577 slang_info_log_error(log, "cannot index a non-array type");
578 return GL_FALSE;
579 }
580 ti->spec.type = _slang_type_base(_ti.spec.type);
581 }
582 slang_typeinfo_destruct(&_ti);
583 }
584 break;
585 case SLANG_OPER_CALL:
586 if (op->fun) {
587 /* we've resolved this call before */
588 slang_type_specifier_copy(&ti->spec, &op->fun->header.type.specifier);
589 }
590 else {
591 slang_function *fun;
592 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
593 space, &ti->spec, &fun, atoms, log))
594 return GL_FALSE;
595 if (fun) {
596 /* save result for future use */
597 op->fun = fun;
598 }
599 else {
600 slang_struct *s =
601 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
602 if (s) {
603 /* struct initializer */
604 ti->spec.type = SLANG_SPEC_STRUCT;
605 ti->spec._struct =
606 (slang_struct *) _slang_alloc(sizeof(slang_struct));
607 if (ti->spec._struct == NULL)
608 return GL_FALSE;
609 if (!slang_struct_construct(ti->spec._struct)) {
610 _slang_free(ti->spec._struct);
611 ti->spec._struct = NULL;
612 return GL_FALSE;
613 }
614 if (!slang_struct_copy(ti->spec._struct, s))
615 return GL_FALSE;
616 }
617 else {
618 /* float, int, vec4, mat3, etc. constructor? */
619 const char *name;
620 slang_type_specifier_type type;
621
622 name = slang_atom_pool_id(atoms, op->a_id);
623 type = slang_type_specifier_type_from_string(name);
624 if (type == SLANG_SPEC_VOID) {
625 slang_info_log_error(log, "undefined function '%s'", name);
626 return GL_FALSE;
627 }
628 ti->spec.type = type;
629 }
630 }
631 }
632 break;
633 case SLANG_OPER_METHOD:
634 /* at this time, GLSL 1.20 only has one method: array.length()
635 * which returns an integer.
636 */
637 ti->spec.type = SLANG_SPEC_INT;
638 break;
639 case SLANG_OPER_FIELD:
640 {
641 slang_typeinfo _ti;
642
643 if (!slang_typeinfo_construct(&_ti))
644 return GL_FALSE;
645 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
646 slang_typeinfo_destruct(&_ti);
647 return GL_FALSE;
648 }
649 if (_ti.spec.type == SLANG_SPEC_STRUCT) {
650 slang_variable *field;
651
652 field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
653 GL_FALSE);
654 if (field == NULL) {
655 slang_typeinfo_destruct(&_ti);
656 return GL_FALSE;
657 }
658 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
659 slang_typeinfo_destruct(&_ti);
660 return GL_FALSE;
661 }
662 ti->can_be_referenced = _ti.can_be_referenced;
663 }
664 else {
665 GLuint rows;
666 const char *swizzle;
667 slang_type_specifier_type base;
668
669 /* determine the swizzle of the field expression */
670 if (!_slang_type_is_vector(_ti.spec.type)) {
671 slang_typeinfo_destruct(&_ti);
672 slang_info_log_error(log, "Can't swizzle scalar expression");
673 return GL_FALSE;
674 }
675 rows = _slang_type_dim(_ti.spec.type);
676 swizzle = slang_atom_pool_id(atoms, op->a_id);
677 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
678 slang_typeinfo_destruct(&_ti);
679 slang_info_log_error(log, "bad swizzle '%s'", swizzle);
680 return GL_FALSE;
681 }
682 ti->is_swizzled = GL_TRUE;
683 ti->can_be_referenced = _ti.can_be_referenced
684 && _slang_is_swizzle_mask(&ti->swz, rows);
685 if (_ti.is_swizzled) {
686 slang_swizzle swz;
687
688 /* swizzle the swizzle */
689 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
690 ti->swz = swz;
691 }
692 base = _slang_type_base(_ti.spec.type);
693 switch (ti->swz.num_components) {
694 case 1:
695 ti->spec.type = base;
696 break;
697 case 2:
698 switch (base) {
699 case SLANG_SPEC_FLOAT:
700 ti->spec.type = SLANG_SPEC_VEC2;
701 break;
702 case SLANG_SPEC_INT:
703 ti->spec.type = SLANG_SPEC_IVEC2;
704 break;
705 case SLANG_SPEC_BOOL:
706 ti->spec.type = SLANG_SPEC_BVEC2;
707 break;
708 default:
709 break;
710 }
711 break;
712 case 3:
713 switch (base) {
714 case SLANG_SPEC_FLOAT:
715 ti->spec.type = SLANG_SPEC_VEC3;
716 break;
717 case SLANG_SPEC_INT:
718 ti->spec.type = SLANG_SPEC_IVEC3;
719 break;
720 case SLANG_SPEC_BOOL:
721 ti->spec.type = SLANG_SPEC_BVEC3;
722 break;
723 default:
724 break;
725 }
726 break;
727 case 4:
728 switch (base) {
729 case SLANG_SPEC_FLOAT:
730 ti->spec.type = SLANG_SPEC_VEC4;
731 break;
732 case SLANG_SPEC_INT:
733 ti->spec.type = SLANG_SPEC_IVEC4;
734 break;
735 case SLANG_SPEC_BOOL:
736 ti->spec.type = SLANG_SPEC_BVEC4;
737 break;
738 default:
739 break;
740 }
741 break;
742 default:
743 break;
744 }
745 }
746 slang_typeinfo_destruct(&_ti);
747 }
748 break;
749 case SLANG_OPER_POSTINCREMENT:
750 case SLANG_OPER_POSTDECREMENT:
751 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
752 return GL_FALSE;
753 ti->can_be_referenced = GL_FALSE;
754 ti->is_swizzled = GL_FALSE;
755 break;
756 default:
757 return GL_FALSE;
758 }
759
760 return GL_TRUE;
761 }
762
763
764 /**
765 * Lookup a function according to name and parameter count/types.
766 */
767 slang_function *
768 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
769 slang_operation * args, GLuint num_args,
770 const slang_name_space * space, slang_atom_pool * atoms,
771 slang_info_log *log, GLboolean *error)
772 {
773 slang_typeinfo arg_ti[100];
774 GLuint i;
775
776 *error = GL_FALSE;
777
778 /* determine type of each argument */
779 assert(num_args < 100);
780 for (i = 0; i < num_args; i++) {
781 if (!slang_typeinfo_construct(&arg_ti[i]))
782 return NULL;
783 if (!_slang_typeof_operation_(&args[i], space, &arg_ti[i], atoms, log)) {
784 return NULL;
785 }
786 }
787
788 /* loop over function scopes */
789 while (funcs) {
790
791 /* look for function with matching name and argument/param types */
792 for (i = 0; i < funcs->num_functions; i++) {
793 slang_function *f = &funcs->functions[i];
794 const GLuint haveRetValue = _slang_function_has_return_value(f);
795 GLuint j;
796
797 if (a_name != f->header.a_name)
798 continue;
799 if (f->param_count - haveRetValue != num_args)
800 continue;
801
802 /* compare parameter / argument types */
803 for (j = 0; j < num_args; j++) {
804 if (!slang_type_specifier_compatible(&arg_ti[j].spec,
805 &f->parameters->variables[j]->type.specifier)) {
806 /* param/arg types don't match */
807 break;
808 }
809
810 /* "out" and "inout" formal parameter requires the actual
811 * argument to be an l-value.
812 */
813 if (!arg_ti[j].can_be_referenced &&
814 (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
815 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT)) {
816 /* param is not an lvalue! */
817 *error = GL_TRUE;
818 return NULL;
819 }
820 }
821
822 if (j == num_args) {
823 /* name and args match! */
824 return f;
825 }
826 }
827
828 funcs = funcs->outer_scope;
829 }
830
831 return NULL;
832 }
833
834
835 /**
836 * Determine if a type is a matrix.
837 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
838 */
839 GLboolean
840 _slang_type_is_matrix(slang_type_specifier_type ty)
841 {
842 switch (ty) {
843 case SLANG_SPEC_MAT2:
844 case SLANG_SPEC_MAT3:
845 case SLANG_SPEC_MAT4:
846 case SLANG_SPEC_MAT23:
847 case SLANG_SPEC_MAT32:
848 case SLANG_SPEC_MAT24:
849 case SLANG_SPEC_MAT42:
850 case SLANG_SPEC_MAT34:
851 case SLANG_SPEC_MAT43:
852 return GL_TRUE;
853 default:
854 return GL_FALSE;
855 }
856 }
857
858
859 /**
860 * Determine if a type is a vector.
861 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
862 */
863 GLboolean
864 _slang_type_is_vector(slang_type_specifier_type ty)
865 {
866 switch (ty) {
867 case SLANG_SPEC_VEC2:
868 case SLANG_SPEC_VEC3:
869 case SLANG_SPEC_VEC4:
870 case SLANG_SPEC_IVEC2:
871 case SLANG_SPEC_IVEC3:
872 case SLANG_SPEC_IVEC4:
873 case SLANG_SPEC_BVEC2:
874 case SLANG_SPEC_BVEC3:
875 case SLANG_SPEC_BVEC4:
876 return GL_TRUE;
877 default:
878 return GL_FALSE;
879 }
880 }
881
882
883 /**
884 * Determine if a type is a float, float vector or float matrix.
885 * \return GL_TRUE if so, GL_FALSE otherwise
886 */
887 GLboolean
888 _slang_type_is_float_vec_mat(slang_type_specifier_type ty)
889 {
890 switch (ty) {
891 case SLANG_SPEC_FLOAT:
892 case SLANG_SPEC_VEC2:
893 case SLANG_SPEC_VEC3:
894 case SLANG_SPEC_VEC4:
895 case SLANG_SPEC_MAT2:
896 case SLANG_SPEC_MAT3:
897 case SLANG_SPEC_MAT4:
898 case SLANG_SPEC_MAT23:
899 case SLANG_SPEC_MAT32:
900 case SLANG_SPEC_MAT24:
901 case SLANG_SPEC_MAT42:
902 case SLANG_SPEC_MAT34:
903 case SLANG_SPEC_MAT43:
904 return GL_TRUE;
905 default:
906 return GL_FALSE;
907 }
908 }
909
910
911 /**
912 * Given a vector type, return the type of the vector's elements.
913 * For a matrix, return the type of the columns.
914 */
915 slang_type_specifier_type
916 _slang_type_base(slang_type_specifier_type ty)
917 {
918 switch (ty) {
919 case SLANG_SPEC_FLOAT:
920 case SLANG_SPEC_VEC2:
921 case SLANG_SPEC_VEC3:
922 case SLANG_SPEC_VEC4:
923 return SLANG_SPEC_FLOAT;
924 case SLANG_SPEC_INT:
925 case SLANG_SPEC_IVEC2:
926 case SLANG_SPEC_IVEC3:
927 case SLANG_SPEC_IVEC4:
928 return SLANG_SPEC_INT;
929 case SLANG_SPEC_BOOL:
930 case SLANG_SPEC_BVEC2:
931 case SLANG_SPEC_BVEC3:
932 case SLANG_SPEC_BVEC4:
933 return SLANG_SPEC_BOOL;
934 case SLANG_SPEC_MAT2:
935 return SLANG_SPEC_VEC2;
936 case SLANG_SPEC_MAT3:
937 return SLANG_SPEC_VEC3;
938 case SLANG_SPEC_MAT4:
939 return SLANG_SPEC_VEC4;
940 case SLANG_SPEC_MAT23:
941 return SLANG_SPEC_VEC3;
942 case SLANG_SPEC_MAT32:
943 return SLANG_SPEC_VEC2;
944 case SLANG_SPEC_MAT24:
945 return SLANG_SPEC_VEC4;
946 case SLANG_SPEC_MAT42:
947 return SLANG_SPEC_VEC2;
948 case SLANG_SPEC_MAT34:
949 return SLANG_SPEC_VEC4;
950 case SLANG_SPEC_MAT43:
951 return SLANG_SPEC_VEC3;
952 default:
953 return SLANG_SPEC_VOID;
954 }
955 }
956
957
958 /**
959 * Return the dimensionality of a vector, or for a matrix, return number
960 * of columns.
961 */
962 GLuint
963 _slang_type_dim(slang_type_specifier_type ty)
964 {
965 switch (ty) {
966 case SLANG_SPEC_FLOAT:
967 case SLANG_SPEC_INT:
968 case SLANG_SPEC_BOOL:
969 return 1;
970 case SLANG_SPEC_VEC2:
971 case SLANG_SPEC_IVEC2:
972 case SLANG_SPEC_BVEC2:
973 case SLANG_SPEC_MAT2:
974 return 2;
975 case SLANG_SPEC_VEC3:
976 case SLANG_SPEC_IVEC3:
977 case SLANG_SPEC_BVEC3:
978 case SLANG_SPEC_MAT3:
979 return 3;
980 case SLANG_SPEC_VEC4:
981 case SLANG_SPEC_IVEC4:
982 case SLANG_SPEC_BVEC4:
983 case SLANG_SPEC_MAT4:
984 return 4;
985
986 case SLANG_SPEC_MAT23:
987 return 2;
988 case SLANG_SPEC_MAT32:
989 return 3;
990 case SLANG_SPEC_MAT24:
991 return 2;
992 case SLANG_SPEC_MAT42:
993 return 4;
994 case SLANG_SPEC_MAT34:
995 return 3;
996 case SLANG_SPEC_MAT43:
997 return 4;
998
999 default:
1000 return 0;
1001 }
1002 }
1003
1004
1005 /**
1006 * Return the GL_* type that corresponds to a SLANG_SPEC_* type.
1007 */
1008 GLenum
1009 _slang_gltype_from_specifier(const slang_type_specifier *type)
1010 {
1011 switch (type->type) {
1012 case SLANG_SPEC_BOOL:
1013 return GL_BOOL;
1014 case SLANG_SPEC_BVEC2:
1015 return GL_BOOL_VEC2;
1016 case SLANG_SPEC_BVEC3:
1017 return GL_BOOL_VEC3;
1018 case SLANG_SPEC_BVEC4:
1019 return GL_BOOL_VEC4;
1020 case SLANG_SPEC_INT:
1021 return GL_INT;
1022 case SLANG_SPEC_IVEC2:
1023 return GL_INT_VEC2;
1024 case SLANG_SPEC_IVEC3:
1025 return GL_INT_VEC3;
1026 case SLANG_SPEC_IVEC4:
1027 return GL_INT_VEC4;
1028 case SLANG_SPEC_FLOAT:
1029 return GL_FLOAT;
1030 case SLANG_SPEC_VEC2:
1031 return GL_FLOAT_VEC2;
1032 case SLANG_SPEC_VEC3:
1033 return GL_FLOAT_VEC3;
1034 case SLANG_SPEC_VEC4:
1035 return GL_FLOAT_VEC4;
1036 case SLANG_SPEC_MAT2:
1037 return GL_FLOAT_MAT2;
1038 case SLANG_SPEC_MAT3:
1039 return GL_FLOAT_MAT3;
1040 case SLANG_SPEC_MAT4:
1041 return GL_FLOAT_MAT4;
1042 case SLANG_SPEC_MAT23:
1043 return GL_FLOAT_MAT2x3;
1044 case SLANG_SPEC_MAT32:
1045 return GL_FLOAT_MAT3x2;
1046 case SLANG_SPEC_MAT24:
1047 return GL_FLOAT_MAT2x4;
1048 case SLANG_SPEC_MAT42:
1049 return GL_FLOAT_MAT4x2;
1050 case SLANG_SPEC_MAT34:
1051 return GL_FLOAT_MAT3x4;
1052 case SLANG_SPEC_MAT43:
1053 return GL_FLOAT_MAT4x3;
1054 case SLANG_SPEC_SAMPLER1D:
1055 return GL_SAMPLER_1D;
1056 case SLANG_SPEC_SAMPLER2D:
1057 return GL_SAMPLER_2D;
1058 case SLANG_SPEC_SAMPLER3D:
1059 return GL_SAMPLER_3D;
1060 case SLANG_SPEC_SAMPLERCUBE:
1061 return GL_SAMPLER_CUBE;
1062 case SLANG_SPEC_SAMPLER1DSHADOW:
1063 return GL_SAMPLER_1D_SHADOW;
1064 case SLANG_SPEC_SAMPLER2DSHADOW:
1065 return GL_SAMPLER_2D_SHADOW;
1066 case SLANG_SPEC_SAMPLER2DRECT:
1067 return GL_SAMPLER_2D_RECT_ARB;
1068 case SLANG_SPEC_SAMPLER2DRECTSHADOW:
1069 return GL_SAMPLER_2D_RECT_SHADOW_ARB;
1070 case SLANG_SPEC_ARRAY:
1071 return _slang_gltype_from_specifier(type->_array);
1072 case SLANG_SPEC_STRUCT:
1073 /* fall-through */
1074 default:
1075 return GL_NONE;
1076 }
1077 }
1078