Merge branch 'glsl-compiler-1' of git+ssh://brianp@git.freedesktop.org/git/mesa/mesa...
[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_error.h"
35 #include "prog_instruction.h"
36
37
38
39
40 /**
41 * Checks if a field selector is a general swizzle (an r-value swizzle
42 * with replicated components or an l-value swizzle mask) for a
43 * vector. Returns GL_TRUE if this is the case, <swz> is filled with
44 * swizzle information. Returns GL_FALSE otherwise.
45 */
46 GLboolean
47 _slang_is_swizzle(const char *field, GLuint rows, slang_swizzle * swz)
48 {
49 GLuint i;
50 GLboolean xyzw = GL_FALSE, rgba = GL_FALSE, stpq = GL_FALSE;
51
52 /* init to undefined.
53 * We rely on undefined/nil values to distinguish between
54 * regular swizzles and writemasks.
55 * For example, the swizzle ".xNNN" is the writemask ".x".
56 * That's different than the swizzle ".xxxx".
57 */
58 for (i = 0; i < 4; i++)
59 swz->swizzle[i] = SWIZZLE_NIL;
60
61 /* the swizzle can be at most 4-component long */
62 swz->num_components = slang_string_length(field);
63 if (swz->num_components > 4)
64 return GL_FALSE;
65
66 for (i = 0; i < swz->num_components; i++) {
67 /* mark which swizzle group is used */
68 switch (field[i]) {
69 case 'x':
70 case 'y':
71 case 'z':
72 case 'w':
73 xyzw = GL_TRUE;
74 break;
75 case 'r':
76 case 'g':
77 case 'b':
78 case 'a':
79 rgba = GL_TRUE;
80 break;
81 case 's':
82 case 't':
83 case 'p':
84 case 'q':
85 stpq = GL_TRUE;
86 break;
87 default:
88 return GL_FALSE;
89 }
90
91 /* collect swizzle component */
92 switch (field[i]) {
93 case 'x':
94 case 'r':
95 case 's':
96 swz->swizzle[i] = 0;
97 break;
98 case 'y':
99 case 'g':
100 case 't':
101 swz->swizzle[i] = 1;
102 break;
103 case 'z':
104 case 'b':
105 case 'p':
106 swz->swizzle[i] = 2;
107 break;
108 case 'w':
109 case 'a':
110 case 'q':
111 swz->swizzle[i] = 3;
112 break;
113 }
114
115 /* check if the component is valid for given vector's row count */
116 if (rows <= swz->swizzle[i])
117 return GL_FALSE;
118 }
119
120 /* only one swizzle group can be used */
121 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
122 return GL_FALSE;
123
124 return GL_TRUE;
125 }
126
127
128
129 /**
130 * Checks if a general swizzle is an l-value swizzle - these swizzles
131 * do not have duplicated fields. Returns GL_TRUE if this is a
132 * swizzle mask. Returns GL_FALSE otherwise
133 */
134 GLboolean
135 _slang_is_swizzle_mask(const slang_swizzle * swz, GLuint rows)
136 {
137 GLuint i, c = 0;
138
139 /* the swizzle may not be longer than the vector dim */
140 if (swz->num_components > rows)
141 return GL_FALSE;
142
143 /* the swizzle components cannot be duplicated */
144 for (i = 0; i < swz->num_components; i++) {
145 if ((c & (1 << swz->swizzle[i])) != 0)
146 return GL_FALSE;
147 c |= 1 << swz->swizzle[i];
148 }
149
150 return GL_TRUE;
151 }
152
153
154 /**
155 * Combines (multiplies) two swizzles to form single swizzle.
156 * Example: "vec.wzyx.yx" --> "vec.zw".
157 */
158 GLvoid
159 _slang_multiply_swizzles(slang_swizzle * dst, const slang_swizzle * left,
160 const slang_swizzle * right)
161 {
162 GLuint i;
163
164 dst->num_components = right->num_components;
165 for (i = 0; i < right->num_components; i++)
166 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
167 }
168
169
170 GLvoid
171 slang_type_specifier_ctr(slang_type_specifier * self)
172 {
173 self->type = SLANG_SPEC_VOID;
174 self->_struct = NULL;
175 self->_array = NULL;
176 }
177
178 GLvoid
179 slang_type_specifier_dtr(slang_type_specifier * self)
180 {
181 if (self->_struct != NULL) {
182 slang_struct_destruct(self->_struct);
183 slang_alloc_free(self->_struct);
184 }
185 if (self->_array != NULL) {
186 slang_type_specifier_dtr(self->_array);
187 slang_alloc_free(self->_array);
188 }
189 }
190
191 GLboolean
192 slang_type_specifier_copy(slang_type_specifier * x,
193 const slang_type_specifier * y)
194 {
195 slang_type_specifier z;
196
197 slang_type_specifier_ctr(&z);
198 z.type = y->type;
199 if (z.type == SLANG_SPEC_STRUCT) {
200 z._struct = (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
201 if (z._struct == NULL) {
202 slang_type_specifier_dtr(&z);
203 return GL_FALSE;
204 }
205 if (!slang_struct_construct(z._struct)) {
206 slang_alloc_free(z._struct);
207 slang_type_specifier_dtr(&z);
208 return GL_FALSE;
209 }
210 if (!slang_struct_copy(z._struct, y->_struct)) {
211 slang_type_specifier_dtr(&z);
212 return GL_FALSE;
213 }
214 }
215 else if (z.type == SLANG_SPEC_ARRAY) {
216 z._array =
217 (slang_type_specifier *)
218 slang_alloc_malloc(sizeof(slang_type_specifier));
219 if (z._array == NULL) {
220 slang_type_specifier_dtr(&z);
221 return GL_FALSE;
222 }
223 slang_type_specifier_ctr(z._array);
224 if (!slang_type_specifier_copy(z._array, y->_array)) {
225 slang_type_specifier_dtr(&z);
226 return GL_FALSE;
227 }
228 }
229 slang_type_specifier_dtr(x);
230 *x = z;
231 return GL_TRUE;
232 }
233
234
235 /**
236 * Test if two types are equal.
237 */
238 GLboolean
239 slang_type_specifier_equal(const slang_type_specifier * x,
240 const slang_type_specifier * y)
241 {
242 if (x->type != y->type)
243 return GL_FALSE;
244 if (x->type == SLANG_SPEC_STRUCT)
245 return slang_struct_equal(x->_struct, y->_struct);
246 if (x->type == SLANG_SPEC_ARRAY)
247 return slang_type_specifier_equal(x->_array, y->_array);
248 return GL_TRUE;
249 }
250
251
252 /**
253 * As above, but allow float/int casting.
254 */
255 static GLboolean
256 slang_type_specifier_compatible(const slang_type_specifier * x,
257 const slang_type_specifier * y)
258 {
259 /* special case: float == int */
260 if (x->type == SLANG_SPEC_INT && y->type == SLANG_SPEC_FLOAT) {
261 return GL_TRUE;
262 }
263 /* XXX may need to add bool/int compatibility, etc */
264
265 if (x->type != y->type)
266 return GL_FALSE;
267 if (x->type == SLANG_SPEC_STRUCT)
268 return slang_struct_equal(x->_struct, y->_struct);
269 if (x->type == SLANG_SPEC_ARRAY)
270 return slang_type_specifier_compatible(x->_array, y->_array);
271 return GL_TRUE;
272 }
273
274
275 GLboolean
276 slang_typeinfo_construct(slang_typeinfo * ti)
277 {
278 slang_type_specifier_ctr(&ti->spec);
279 ti->array_len = 0;
280 return GL_TRUE;
281 }
282
283 GLvoid
284 slang_typeinfo_destruct(slang_typeinfo * ti)
285 {
286 slang_type_specifier_dtr(&ti->spec);
287 }
288
289
290 /**
291 * Determine the return type of a function.
292 * \param name name of the function
293 * \param params array of function parameters
294 * \param num_params number of parameters
295 * \param space namespace to use
296 * \param spec returns the function's type
297 * \param atoms atom pool
298 * \return GL_TRUE for success, GL_FALSE if failure
299 */
300 static GLboolean
301 typeof_existing_function(const char *name, const slang_operation * params,
302 GLuint num_params,
303 const slang_name_space * space,
304 slang_type_specifier * spec,
305 slang_atom_pool * atoms)
306 {
307 slang_atom atom;
308 GLboolean exists;
309
310 atom = slang_atom_pool_atom(atoms, name);
311 if (!_slang_typeof_function(atom, params, num_params, space, spec,
312 &exists, atoms))
313 return GL_FALSE;
314 return exists;
315 }
316
317 GLboolean
318 _slang_typeof_operation(const slang_assemble_ctx * A,
319 const slang_operation * op,
320 slang_typeinfo * ti)
321 {
322 return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
323 }
324
325
326 /**
327 * Determine the return type of an operation.
328 * \param op the operation node
329 * \param space the namespace to use
330 * \param ti the returned type
331 * \param atoms atom pool
332 * \return GL_TRUE for success, GL_FALSE if failure
333 */
334 GLboolean
335 _slang_typeof_operation_(const slang_operation * op,
336 const slang_name_space * space,
337 slang_typeinfo * ti,
338 slang_atom_pool * atoms)
339 {
340 ti->can_be_referenced = GL_FALSE;
341 ti->is_swizzled = GL_FALSE;
342
343 switch (op->type) {
344 case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
345 case SLANG_OPER_BLOCK_NEW_SCOPE:
346 case SLANG_OPER_VARIABLE_DECL:
347 case SLANG_OPER_ASM:
348 case SLANG_OPER_BREAK:
349 case SLANG_OPER_CONTINUE:
350 case SLANG_OPER_DISCARD:
351 case SLANG_OPER_RETURN:
352 case SLANG_OPER_IF:
353 case SLANG_OPER_WHILE:
354 case SLANG_OPER_DO:
355 case SLANG_OPER_FOR:
356 case SLANG_OPER_VOID:
357 ti->spec.type = SLANG_SPEC_VOID;
358 break;
359 case SLANG_OPER_EXPRESSION:
360 case SLANG_OPER_ASSIGN:
361 case SLANG_OPER_ADDASSIGN:
362 case SLANG_OPER_SUBASSIGN:
363 case SLANG_OPER_MULASSIGN:
364 case SLANG_OPER_DIVASSIGN:
365 case SLANG_OPER_PREINCREMENT:
366 case SLANG_OPER_PREDECREMENT:
367 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
368 return GL_FALSE;
369 break;
370 case SLANG_OPER_LITERAL_BOOL:
371 if (op->literal_size == 1)
372 ti->spec.type = SLANG_SPEC_BOOL;
373 else if (op->literal_size == 2)
374 ti->spec.type = SLANG_SPEC_BVEC2;
375 else if (op->literal_size == 3)
376 ti->spec.type = SLANG_SPEC_BVEC3;
377 else if (op->literal_size == 4)
378 ti->spec.type = SLANG_SPEC_BVEC4;
379 else {
380 _mesa_problem(NULL,
381 "Unexpected bool literal_size %d in _slang_typeof_operation()",
382 op->literal_size);
383 ti->spec.type = SLANG_SPEC_BOOL;
384 }
385 break;
386 case SLANG_OPER_LOGICALOR:
387 case SLANG_OPER_LOGICALXOR:
388 case SLANG_OPER_LOGICALAND:
389 case SLANG_OPER_EQUAL:
390 case SLANG_OPER_NOTEQUAL:
391 case SLANG_OPER_LESS:
392 case SLANG_OPER_GREATER:
393 case SLANG_OPER_LESSequal:
394 case SLANG_OPER_GREATERequal:
395 case SLANG_OPER_NOT:
396 ti->spec.type = SLANG_SPEC_BOOL;
397 break;
398 case SLANG_OPER_LITERAL_INT:
399 if (op->literal_size == 1)
400 ti->spec.type = SLANG_SPEC_INT;
401 else if (op->literal_size == 2)
402 ti->spec.type = SLANG_SPEC_IVEC2;
403 else if (op->literal_size == 3)
404 ti->spec.type = SLANG_SPEC_IVEC3;
405 else if (op->literal_size == 4)
406 ti->spec.type = SLANG_SPEC_IVEC4;
407 else {
408 _mesa_problem(NULL,
409 "Unexpected int literal_size %d in _slang_typeof_operation()",
410 op->literal_size);
411 ti->spec.type = SLANG_SPEC_INT;
412 }
413 break;
414 case SLANG_OPER_LITERAL_FLOAT:
415 if (op->literal_size == 1)
416 ti->spec.type = SLANG_SPEC_FLOAT;
417 else if (op->literal_size == 2)
418 ti->spec.type = SLANG_SPEC_VEC2;
419 else if (op->literal_size == 3)
420 ti->spec.type = SLANG_SPEC_VEC3;
421 else if (op->literal_size == 4)
422 ti->spec.type = SLANG_SPEC_VEC4;
423 else {
424 _mesa_problem(NULL,
425 "Unexpected float literal_size %d in _slang_typeof_operation()",
426 op->literal_size);
427 ti->spec.type = SLANG_SPEC_FLOAT;
428 }
429 break;
430 case SLANG_OPER_IDENTIFIER:
431 {
432 slang_variable *var;
433 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
434 if (var == NULL)
435 RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
436 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
437 RETURN_OUT_OF_MEMORY();
438 ti->can_be_referenced = GL_TRUE;
439 ti->array_len = var->array_len;
440 }
441 break;
442 case SLANG_OPER_SEQUENCE:
443 /* TODO: check [0] and [1] if they match */
444 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
445 RETURN_NIL();
446 ti->can_be_referenced = GL_FALSE;
447 ti->is_swizzled = GL_FALSE;
448 break;
449 /*case SLANG_OPER_MODASSIGN: */
450 /*case SLANG_OPER_LSHASSIGN: */
451 /*case SLANG_OPER_RSHASSIGN: */
452 /*case SLANG_OPER_ORASSIGN: */
453 /*case SLANG_OPER_XORASSIGN: */
454 /*case SLANG_OPER_ANDASSIGN: */
455 case SLANG_OPER_SELECT:
456 /* TODO: check [1] and [2] if they match */
457 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
458 RETURN_NIL();
459 ti->can_be_referenced = GL_FALSE;
460 ti->is_swizzled = GL_FALSE;
461 break;
462 /*case SLANG_OPER_BITOR: */
463 /*case SLANG_OPER_BITXOR: */
464 /*case SLANG_OPER_BITAND: */
465 /*case SLANG_OPER_LSHIFT: */
466 /*case SLANG_OPER_RSHIFT: */
467 case SLANG_OPER_ADD:
468 if (!typeof_existing_function("+", op->children, 2, space,
469 &ti->spec, atoms))
470 RETURN_NIL();
471 break;
472 case SLANG_OPER_SUBTRACT:
473 if (!typeof_existing_function("-", op->children, 2, space,
474 &ti->spec, atoms))
475 RETURN_NIL();
476 break;
477 case SLANG_OPER_MULTIPLY:
478 if (!typeof_existing_function("*", op->children, 2, space,
479 &ti->spec, atoms))
480 RETURN_NIL();
481 break;
482 case SLANG_OPER_DIVIDE:
483 if (!typeof_existing_function("/", op->children, 2, space,
484 &ti->spec, atoms))
485 RETURN_NIL();
486 break;
487 /*case SLANG_OPER_MODULUS: */
488 case SLANG_OPER_PLUS:
489 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
490 RETURN_NIL();
491 ti->can_be_referenced = GL_FALSE;
492 ti->is_swizzled = GL_FALSE;
493 break;
494 case SLANG_OPER_MINUS:
495 if (!typeof_existing_function("-", op->children, 1, space,
496 &ti->spec, atoms))
497 RETURN_NIL();
498 break;
499 /*case SLANG_OPER_COMPLEMENT: */
500 case SLANG_OPER_SUBSCRIPT:
501 {
502 slang_typeinfo _ti;
503
504 if (!slang_typeinfo_construct(&_ti))
505 RETURN_NIL();
506 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
507 slang_typeinfo_destruct(&_ti);
508 RETURN_NIL();
509 }
510 ti->can_be_referenced = _ti.can_be_referenced;
511 if (_ti.spec.type == SLANG_SPEC_ARRAY) {
512 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
513 slang_typeinfo_destruct(&_ti);
514 RETURN_NIL();
515 }
516 }
517 else {
518 if (!_slang_type_is_vector(_ti.spec.type)
519 && !_slang_type_is_matrix(_ti.spec.type)) {
520 slang_typeinfo_destruct(&_ti);
521 RETURN_ERROR("cannot index a non-array type", 0);
522 }
523 ti->spec.type = _slang_type_base(_ti.spec.type);
524 }
525 slang_typeinfo_destruct(&_ti);
526 }
527 break;
528 case SLANG_OPER_CALL:
529 {
530 GLboolean exists;
531
532 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
533 space, &ti->spec, &exists, atoms))
534 RETURN_NIL();
535 if (!exists) {
536 slang_struct *s =
537 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
538 if (s != NULL) {
539 ti->spec.type = SLANG_SPEC_STRUCT;
540 ti->spec._struct =
541 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
542 if (ti->spec._struct == NULL)
543 RETURN_NIL();
544 if (!slang_struct_construct(ti->spec._struct)) {
545 slang_alloc_free(ti->spec._struct);
546 ti->spec._struct = NULL;
547 RETURN_NIL();
548 }
549 if (!slang_struct_copy(ti->spec._struct, s))
550 RETURN_NIL();
551 }
552 else {
553 const char *name;
554 slang_type_specifier_type type;
555
556 name = slang_atom_pool_id(atoms, op->a_id);
557 type = slang_type_specifier_type_from_string(name);
558 if (type == SLANG_SPEC_VOID)
559 RETURN_ERROR2("function not found", name, 0);
560 ti->spec.type = type;
561 }
562 }
563 }
564 break;
565 case SLANG_OPER_FIELD:
566 {
567 slang_typeinfo _ti;
568
569 if (!slang_typeinfo_construct(&_ti))
570 RETURN_NIL();
571 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
572 slang_typeinfo_destruct(&_ti);
573 RETURN_NIL();
574 }
575 if (_ti.spec.type == SLANG_SPEC_STRUCT) {
576 slang_variable *field;
577
578 field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
579 GL_FALSE);
580 if (field == NULL) {
581 slang_typeinfo_destruct(&_ti);
582 RETURN_NIL();
583 }
584 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
585 slang_typeinfo_destruct(&_ti);
586 RETURN_NIL();
587 }
588 ti->can_be_referenced = _ti.can_be_referenced;
589 }
590 else {
591 GLuint rows;
592 const char *swizzle;
593 slang_type_specifier_type base;
594
595 /* determine the swizzle of the field expression */
596 #if 000
597 if (!_slang_type_is_vector(_ti.spec.type)) {
598 slang_typeinfo_destruct(&_ti);
599 RETURN_ERROR("Can't swizzle scalar expression", 0);
600 }
601 #endif
602 rows = _slang_type_dim(_ti.spec.type);
603 swizzle = slang_atom_pool_id(atoms, op->a_id);
604 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
605 slang_typeinfo_destruct(&_ti);
606 RETURN_ERROR("Bad swizzle", 0);
607 }
608 ti->is_swizzled = GL_TRUE;
609 ti->can_be_referenced = _ti.can_be_referenced
610 && _slang_is_swizzle_mask(&ti->swz, rows);
611 if (_ti.is_swizzled) {
612 slang_swizzle swz;
613
614 /* swizzle the swizzle */
615 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
616 ti->swz = swz;
617 }
618 base = _slang_type_base(_ti.spec.type);
619 switch (ti->swz.num_components) {
620 case 1:
621 ti->spec.type = base;
622 break;
623 case 2:
624 switch (base) {
625 case SLANG_SPEC_FLOAT:
626 ti->spec.type = SLANG_SPEC_VEC2;
627 break;
628 case SLANG_SPEC_INT:
629 ti->spec.type = SLANG_SPEC_IVEC2;
630 break;
631 case SLANG_SPEC_BOOL:
632 ti->spec.type = SLANG_SPEC_BVEC2;
633 break;
634 default:
635 break;
636 }
637 break;
638 case 3:
639 switch (base) {
640 case SLANG_SPEC_FLOAT:
641 ti->spec.type = SLANG_SPEC_VEC3;
642 break;
643 case SLANG_SPEC_INT:
644 ti->spec.type = SLANG_SPEC_IVEC3;
645 break;
646 case SLANG_SPEC_BOOL:
647 ti->spec.type = SLANG_SPEC_BVEC3;
648 break;
649 default:
650 break;
651 }
652 break;
653 case 4:
654 switch (base) {
655 case SLANG_SPEC_FLOAT:
656 ti->spec.type = SLANG_SPEC_VEC4;
657 break;
658 case SLANG_SPEC_INT:
659 ti->spec.type = SLANG_SPEC_IVEC4;
660 break;
661 case SLANG_SPEC_BOOL:
662 ti->spec.type = SLANG_SPEC_BVEC4;
663 break;
664 default:
665 break;
666 }
667 break;
668 default:
669 break;
670 }
671 }
672 slang_typeinfo_destruct(&_ti);
673 }
674 break;
675 case SLANG_OPER_POSTINCREMENT:
676 case SLANG_OPER_POSTDECREMENT:
677 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
678 RETURN_NIL();
679 ti->can_be_referenced = GL_FALSE;
680 ti->is_swizzled = GL_FALSE;
681 break;
682 default:
683 RETURN_NIL();
684 }
685
686 return GL_TRUE;
687 }
688
689
690 /**
691 * Lookup a function according to name and parameter count/types.
692 */
693 slang_function *
694 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
695 const slang_operation * args, GLuint num_args,
696 const slang_name_space * space, slang_atom_pool * atoms)
697 {
698 GLuint i;
699
700 for (i = 0; i < funcs->num_functions; i++) {
701 slang_function *f = &funcs->functions[i];
702 const GLuint haveRetValue = _slang_function_has_return_value(f);
703 GLuint j;
704
705 if (a_name != f->header.a_name)
706 continue;
707 if (f->param_count - haveRetValue != num_args)
708 continue;
709
710 /* compare parameter / argument types */
711 for (j = 0; j < num_args; j++) {
712 slang_typeinfo ti;
713
714 if (!slang_typeinfo_construct(&ti))
715 return NULL;
716 if (!_slang_typeof_operation_(&args[j], space, &ti, atoms)) {
717 slang_typeinfo_destruct(&ti);
718 return NULL;
719 }
720 if (!slang_type_specifier_compatible(&ti.spec,
721 &f->parameters->variables[j]->type.specifier)) {
722 slang_typeinfo_destruct(&ti);
723 break;
724 }
725 slang_typeinfo_destruct(&ti);
726
727 /* "out" and "inout" formal parameter requires the actual
728 * parameter to be l-value.
729 */
730 if (!ti.can_be_referenced &&
731 (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
732 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT))
733 break;
734 }
735 if (j == num_args)
736 return f;
737 }
738 if (funcs->outer_scope != NULL)
739 return _slang_locate_function(funcs->outer_scope, a_name, args,
740 num_args, space, atoms);
741 return NULL;
742 }
743
744
745
746 /**
747 * Determine the return type of a function.
748 * \param a_name the function name
749 * \param param function parameters (overloading)
750 * \param num_params number of parameters to function
751 * \param space namespace to search
752 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
753 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
754 */
755 GLboolean
756 _slang_typeof_function(slang_atom a_name, const slang_operation * params,
757 GLuint num_params,
758 const slang_name_space * space,
759 slang_type_specifier * spec, GLboolean * exists,
760 slang_atom_pool * atoms)
761 {
762 slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
763 num_params, space, atoms);
764 *exists = fun != NULL;
765 if (!fun)
766 return GL_TRUE; /* yes, not false */
767 return slang_type_specifier_copy(spec, &fun->header.type.specifier);
768 }
769
770
771
772 /**
773 * Determine if a type is a matrix.
774 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
775 */
776 GLboolean
777 _slang_type_is_matrix(slang_type_specifier_type ty)
778 {
779 switch (ty) {
780 case SLANG_SPEC_MAT2:
781 case SLANG_SPEC_MAT3:
782 case SLANG_SPEC_MAT4:
783 return GL_TRUE;
784 default:
785 return GL_FALSE;
786 }
787 }
788
789
790 /**
791 * Determine if a type is a vector.
792 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
793 */
794 GLboolean
795 _slang_type_is_vector(slang_type_specifier_type ty)
796 {
797 switch (ty) {
798 case SLANG_SPEC_VEC2:
799 case SLANG_SPEC_VEC3:
800 case SLANG_SPEC_VEC4:
801 case SLANG_SPEC_IVEC2:
802 case SLANG_SPEC_IVEC3:
803 case SLANG_SPEC_IVEC4:
804 case SLANG_SPEC_BVEC2:
805 case SLANG_SPEC_BVEC3:
806 case SLANG_SPEC_BVEC4:
807 return GL_TRUE;
808 default:
809 return GL_FALSE;
810 }
811 }
812
813
814 /**
815 * Given a vector type, return the type of the vector's elements
816 */
817 slang_type_specifier_type
818 _slang_type_base(slang_type_specifier_type ty)
819 {
820 switch (ty) {
821 case SLANG_SPEC_FLOAT:
822 case SLANG_SPEC_VEC2:
823 case SLANG_SPEC_VEC3:
824 case SLANG_SPEC_VEC4:
825 return SLANG_SPEC_FLOAT;
826 case SLANG_SPEC_INT:
827 case SLANG_SPEC_IVEC2:
828 case SLANG_SPEC_IVEC3:
829 case SLANG_SPEC_IVEC4:
830 return SLANG_SPEC_INT;
831 case SLANG_SPEC_BOOL:
832 case SLANG_SPEC_BVEC2:
833 case SLANG_SPEC_BVEC3:
834 case SLANG_SPEC_BVEC4:
835 return SLANG_SPEC_BOOL;
836 case SLANG_SPEC_MAT2:
837 return SLANG_SPEC_VEC2;
838 case SLANG_SPEC_MAT3:
839 return SLANG_SPEC_VEC3;
840 case SLANG_SPEC_MAT4:
841 return SLANG_SPEC_VEC4;
842 default:
843 return SLANG_SPEC_VOID;
844 }
845 }
846
847
848 /**
849 * Return the dimensionality of a vector or matrix type.
850 */
851 GLuint
852 _slang_type_dim(slang_type_specifier_type ty)
853 {
854 switch (ty) {
855 case SLANG_SPEC_FLOAT:
856 case SLANG_SPEC_INT:
857 case SLANG_SPEC_BOOL:
858 return 1;
859 case SLANG_SPEC_VEC2:
860 case SLANG_SPEC_IVEC2:
861 case SLANG_SPEC_BVEC2:
862 case SLANG_SPEC_MAT2:
863 return 2;
864 case SLANG_SPEC_VEC3:
865 case SLANG_SPEC_IVEC3:
866 case SLANG_SPEC_BVEC3:
867 case SLANG_SPEC_MAT3:
868 return 3;
869 case SLANG_SPEC_VEC4:
870 case SLANG_SPEC_IVEC4:
871 case SLANG_SPEC_BVEC4:
872 case SLANG_SPEC_MAT4:
873 return 4;
874 default:
875 return 0;
876 }
877 }