s/equal/EQUAL/, fix bugs in logical or/and code.
[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 "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 slang_info_log *log)
307 {
308 slang_atom atom;
309 GLboolean exists;
310
311 atom = slang_atom_pool_atom(atoms, name);
312 if (!_slang_typeof_function(atom, params, num_params, space, spec,
313 &exists, atoms, log))
314 return GL_FALSE;
315 return exists;
316 }
317
318 GLboolean
319 _slang_typeof_operation(const slang_assemble_ctx * A,
320 const slang_operation * op,
321 slang_typeinfo * ti)
322 {
323 return _slang_typeof_operation_(op, &A->space, ti, A->atoms, A->log);
324 }
325
326
327 /**
328 * Determine the return type of an operation.
329 * \param op the operation node
330 * \param space the namespace to use
331 * \param ti the returned type
332 * \param atoms atom pool
333 * \return GL_TRUE for success, GL_FALSE if failure
334 */
335 GLboolean
336 _slang_typeof_operation_(const slang_operation * op,
337 const slang_name_space * space,
338 slang_typeinfo * ti,
339 slang_atom_pool * atoms,
340 slang_info_log *log)
341 {
342 ti->can_be_referenced = GL_FALSE;
343 ti->is_swizzled = GL_FALSE;
344
345 switch (op->type) {
346 case SLANG_OPER_BLOCK_NO_NEW_SCOPE:
347 case SLANG_OPER_BLOCK_NEW_SCOPE:
348 case SLANG_OPER_VARIABLE_DECL:
349 case SLANG_OPER_ASM:
350 case SLANG_OPER_BREAK:
351 case SLANG_OPER_CONTINUE:
352 case SLANG_OPER_DISCARD:
353 case SLANG_OPER_RETURN:
354 case SLANG_OPER_IF:
355 case SLANG_OPER_WHILE:
356 case SLANG_OPER_DO:
357 case SLANG_OPER_FOR:
358 case SLANG_OPER_VOID:
359 ti->spec.type = SLANG_SPEC_VOID;
360 break;
361 case SLANG_OPER_EXPRESSION:
362 case SLANG_OPER_ASSIGN:
363 case SLANG_OPER_ADDASSIGN:
364 case SLANG_OPER_SUBASSIGN:
365 case SLANG_OPER_MULASSIGN:
366 case SLANG_OPER_DIVASSIGN:
367 case SLANG_OPER_PREINCREMENT:
368 case SLANG_OPER_PREDECREMENT:
369 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
370 return GL_FALSE;
371 break;
372 case SLANG_OPER_LITERAL_BOOL:
373 if (op->literal_size == 1)
374 ti->spec.type = SLANG_SPEC_BOOL;
375 else if (op->literal_size == 2)
376 ti->spec.type = SLANG_SPEC_BVEC2;
377 else if (op->literal_size == 3)
378 ti->spec.type = SLANG_SPEC_BVEC3;
379 else if (op->literal_size == 4)
380 ti->spec.type = SLANG_SPEC_BVEC4;
381 else {
382 _mesa_problem(NULL,
383 "Unexpected bool literal_size %d in _slang_typeof_operation()",
384 op->literal_size);
385 ti->spec.type = SLANG_SPEC_BOOL;
386 }
387 break;
388 case SLANG_OPER_LOGICALOR:
389 case SLANG_OPER_LOGICALXOR:
390 case SLANG_OPER_LOGICALAND:
391 case SLANG_OPER_EQUAL:
392 case SLANG_OPER_NOTEQUAL:
393 case SLANG_OPER_LESS:
394 case SLANG_OPER_GREATER:
395 case SLANG_OPER_LESSEQUAL:
396 case SLANG_OPER_GREATEREQUAL:
397 case SLANG_OPER_NOT:
398 ti->spec.type = SLANG_SPEC_BOOL;
399 break;
400 case SLANG_OPER_LITERAL_INT:
401 if (op->literal_size == 1)
402 ti->spec.type = SLANG_SPEC_INT;
403 else if (op->literal_size == 2)
404 ti->spec.type = SLANG_SPEC_IVEC2;
405 else if (op->literal_size == 3)
406 ti->spec.type = SLANG_SPEC_IVEC3;
407 else if (op->literal_size == 4)
408 ti->spec.type = SLANG_SPEC_IVEC4;
409 else {
410 _mesa_problem(NULL,
411 "Unexpected int literal_size %d in _slang_typeof_operation()",
412 op->literal_size);
413 ti->spec.type = SLANG_SPEC_INT;
414 }
415 break;
416 case SLANG_OPER_LITERAL_FLOAT:
417 if (op->literal_size == 1)
418 ti->spec.type = SLANG_SPEC_FLOAT;
419 else if (op->literal_size == 2)
420 ti->spec.type = SLANG_SPEC_VEC2;
421 else if (op->literal_size == 3)
422 ti->spec.type = SLANG_SPEC_VEC3;
423 else if (op->literal_size == 4)
424 ti->spec.type = SLANG_SPEC_VEC4;
425 else {
426 _mesa_problem(NULL,
427 "Unexpected float literal_size %d in _slang_typeof_operation()",
428 op->literal_size);
429 ti->spec.type = SLANG_SPEC_FLOAT;
430 }
431 break;
432 case SLANG_OPER_IDENTIFIER:
433 {
434 slang_variable *var;
435 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
436 if (!var) {
437 slang_info_log_error(log, "undefined variable '%s'",
438 (char *) op->a_id);
439 return GL_FALSE;
440 }
441 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier)) {
442 slang_info_log_memory(log);
443 return GL_FALSE;
444 }
445 ti->can_be_referenced = GL_TRUE;
446 ti->array_len = var->array_len;
447 }
448 break;
449 case SLANG_OPER_SEQUENCE:
450 /* TODO: check [0] and [1] if they match */
451 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
452 return GL_FALSE;
453 }
454 ti->can_be_referenced = GL_FALSE;
455 ti->is_swizzled = GL_FALSE;
456 break;
457 /*case SLANG_OPER_MODASSIGN: */
458 /*case SLANG_OPER_LSHASSIGN: */
459 /*case SLANG_OPER_RSHASSIGN: */
460 /*case SLANG_OPER_ORASSIGN: */
461 /*case SLANG_OPER_XORASSIGN: */
462 /*case SLANG_OPER_ANDASSIGN: */
463 case SLANG_OPER_SELECT:
464 /* TODO: check [1] and [2] if they match */
465 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms, log)) {
466 return GL_FALSE;
467 }
468 ti->can_be_referenced = GL_FALSE;
469 ti->is_swizzled = GL_FALSE;
470 break;
471 /*case SLANG_OPER_BITOR: */
472 /*case SLANG_OPER_BITXOR: */
473 /*case SLANG_OPER_BITAND: */
474 /*case SLANG_OPER_LSHIFT: */
475 /*case SLANG_OPER_RSHIFT: */
476 case SLANG_OPER_ADD:
477 if (!typeof_existing_function("+", op->children, 2, space,
478 &ti->spec, atoms, log))
479 return GL_FALSE;
480 break;
481 case SLANG_OPER_SUBTRACT:
482 if (!typeof_existing_function("-", op->children, 2, space,
483 &ti->spec, atoms, log))
484 return GL_FALSE;
485 break;
486 case SLANG_OPER_MULTIPLY:
487 if (!typeof_existing_function("*", op->children, 2, space,
488 &ti->spec, atoms, log))
489 return GL_FALSE;
490 break;
491 case SLANG_OPER_DIVIDE:
492 if (!typeof_existing_function("/", op->children, 2, space,
493 &ti->spec, atoms, log))
494 return GL_FALSE;
495 break;
496 /*case SLANG_OPER_MODULUS: */
497 case SLANG_OPER_PLUS:
498 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
499 return GL_FALSE;
500 ti->can_be_referenced = GL_FALSE;
501 ti->is_swizzled = GL_FALSE;
502 break;
503 case SLANG_OPER_MINUS:
504 if (!typeof_existing_function("-", op->children, 1, space,
505 &ti->spec, atoms, log))
506 return GL_FALSE;
507 break;
508 /*case SLANG_OPER_COMPLEMENT: */
509 case SLANG_OPER_SUBSCRIPT:
510 {
511 slang_typeinfo _ti;
512
513 if (!slang_typeinfo_construct(&_ti))
514 return GL_FALSE;
515 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
516 slang_typeinfo_destruct(&_ti);
517 return GL_FALSE;
518 }
519 ti->can_be_referenced = _ti.can_be_referenced;
520 if (_ti.spec.type == SLANG_SPEC_ARRAY) {
521 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
522 slang_typeinfo_destruct(&_ti);
523 return GL_FALSE;
524 }
525 }
526 else {
527 if (!_slang_type_is_vector(_ti.spec.type)
528 && !_slang_type_is_matrix(_ti.spec.type)) {
529 slang_typeinfo_destruct(&_ti);
530 slang_info_log_error(log, "cannot index a non-array type");
531 return GL_FALSE;
532 }
533 ti->spec.type = _slang_type_base(_ti.spec.type);
534 }
535 slang_typeinfo_destruct(&_ti);
536 }
537 break;
538 case SLANG_OPER_CALL:
539 {
540 GLboolean exists;
541
542 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
543 space, &ti->spec, &exists, atoms, log))
544 return GL_FALSE;
545 if (!exists) {
546 slang_struct *s =
547 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
548 if (s != NULL) {
549 ti->spec.type = SLANG_SPEC_STRUCT;
550 ti->spec._struct =
551 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
552 if (ti->spec._struct == NULL)
553 return GL_FALSE;
554 if (!slang_struct_construct(ti->spec._struct)) {
555 slang_alloc_free(ti->spec._struct);
556 ti->spec._struct = NULL;
557 return GL_FALSE;
558 }
559 if (!slang_struct_copy(ti->spec._struct, s))
560 return GL_FALSE;
561 }
562 else {
563 const char *name;
564 slang_type_specifier_type type;
565
566 name = slang_atom_pool_id(atoms, op->a_id);
567 type = slang_type_specifier_type_from_string(name);
568 if (type == SLANG_SPEC_VOID) {
569 slang_info_log_error(log, "undefined function '%s'", name);
570 return GL_FALSE;
571 }
572 ti->spec.type = type;
573 }
574 }
575 }
576 break;
577 case SLANG_OPER_FIELD:
578 {
579 slang_typeinfo _ti;
580
581 if (!slang_typeinfo_construct(&_ti))
582 return GL_FALSE;
583 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms, log)) {
584 slang_typeinfo_destruct(&_ti);
585 return GL_FALSE;
586 }
587 if (_ti.spec.type == SLANG_SPEC_STRUCT) {
588 slang_variable *field;
589
590 field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
591 GL_FALSE);
592 if (field == NULL) {
593 slang_typeinfo_destruct(&_ti);
594 return GL_FALSE;
595 }
596 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
597 slang_typeinfo_destruct(&_ti);
598 return GL_FALSE;
599 }
600 ti->can_be_referenced = _ti.can_be_referenced;
601 }
602 else {
603 GLuint rows;
604 const char *swizzle;
605 slang_type_specifier_type base;
606
607 /* determine the swizzle of the field expression */
608 if (!_slang_type_is_vector(_ti.spec.type)) {
609 slang_typeinfo_destruct(&_ti);
610 slang_info_log_error(log, "Can't swizzle scalar expression");
611 return GL_FALSE;
612 }
613 rows = _slang_type_dim(_ti.spec.type);
614 swizzle = slang_atom_pool_id(atoms, op->a_id);
615 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
616 slang_typeinfo_destruct(&_ti);
617 slang_info_log_error(log, "bad swizzle '%s'", swizzle);
618 return GL_FALSE;
619 }
620 ti->is_swizzled = GL_TRUE;
621 ti->can_be_referenced = _ti.can_be_referenced
622 && _slang_is_swizzle_mask(&ti->swz, rows);
623 if (_ti.is_swizzled) {
624 slang_swizzle swz;
625
626 /* swizzle the swizzle */
627 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
628 ti->swz = swz;
629 }
630 base = _slang_type_base(_ti.spec.type);
631 switch (ti->swz.num_components) {
632 case 1:
633 ti->spec.type = base;
634 break;
635 case 2:
636 switch (base) {
637 case SLANG_SPEC_FLOAT:
638 ti->spec.type = SLANG_SPEC_VEC2;
639 break;
640 case SLANG_SPEC_INT:
641 ti->spec.type = SLANG_SPEC_IVEC2;
642 break;
643 case SLANG_SPEC_BOOL:
644 ti->spec.type = SLANG_SPEC_BVEC2;
645 break;
646 default:
647 break;
648 }
649 break;
650 case 3:
651 switch (base) {
652 case SLANG_SPEC_FLOAT:
653 ti->spec.type = SLANG_SPEC_VEC3;
654 break;
655 case SLANG_SPEC_INT:
656 ti->spec.type = SLANG_SPEC_IVEC3;
657 break;
658 case SLANG_SPEC_BOOL:
659 ti->spec.type = SLANG_SPEC_BVEC3;
660 break;
661 default:
662 break;
663 }
664 break;
665 case 4:
666 switch (base) {
667 case SLANG_SPEC_FLOAT:
668 ti->spec.type = SLANG_SPEC_VEC4;
669 break;
670 case SLANG_SPEC_INT:
671 ti->spec.type = SLANG_SPEC_IVEC4;
672 break;
673 case SLANG_SPEC_BOOL:
674 ti->spec.type = SLANG_SPEC_BVEC4;
675 break;
676 default:
677 break;
678 }
679 break;
680 default:
681 break;
682 }
683 }
684 slang_typeinfo_destruct(&_ti);
685 }
686 break;
687 case SLANG_OPER_POSTINCREMENT:
688 case SLANG_OPER_POSTDECREMENT:
689 if (!_slang_typeof_operation_(op->children, space, ti, atoms, log))
690 return GL_FALSE;
691 ti->can_be_referenced = GL_FALSE;
692 ti->is_swizzled = GL_FALSE;
693 break;
694 default:
695 return GL_FALSE;
696 }
697
698 return GL_TRUE;
699 }
700
701
702 /**
703 * Lookup a function according to name and parameter count/types.
704 */
705 slang_function *
706 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
707 const slang_operation * args, GLuint num_args,
708 const slang_name_space * space, slang_atom_pool * atoms,
709 slang_info_log *log)
710 {
711 GLuint i;
712
713 for (i = 0; i < funcs->num_functions; i++) {
714 slang_function *f = &funcs->functions[i];
715 const GLuint haveRetValue = _slang_function_has_return_value(f);
716 GLuint j;
717
718 if (a_name != f->header.a_name)
719 continue;
720 if (f->param_count - haveRetValue != num_args)
721 continue;
722
723 /* compare parameter / argument types */
724 for (j = 0; j < num_args; j++) {
725 slang_typeinfo ti;
726
727 if (!slang_typeinfo_construct(&ti))
728 return NULL;
729 if (!_slang_typeof_operation_(&args[j], space, &ti, atoms, log)) {
730 slang_typeinfo_destruct(&ti);
731 return NULL;
732 }
733 if (!slang_type_specifier_compatible(&ti.spec,
734 &f->parameters->variables[j]->type.specifier)) {
735 slang_typeinfo_destruct(&ti);
736 break;
737 }
738 slang_typeinfo_destruct(&ti);
739
740 /* "out" and "inout" formal parameter requires the actual
741 * parameter to be l-value.
742 */
743 if (!ti.can_be_referenced &&
744 (f->parameters->variables[j]->type.qualifier == SLANG_QUAL_OUT ||
745 f->parameters->variables[j]->type.qualifier == SLANG_QUAL_INOUT))
746 break;
747 }
748 if (j == num_args)
749 return f;
750 }
751 if (funcs->outer_scope != NULL)
752 return _slang_locate_function(funcs->outer_scope, a_name, args,
753 num_args, space, atoms, log);
754 return NULL;
755 }
756
757
758
759 /**
760 * Determine the return type of a function.
761 * \param a_name the function name
762 * \param param function parameters (overloading)
763 * \param num_params number of parameters to function
764 * \param space namespace to search
765 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
766 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
767 */
768 GLboolean
769 _slang_typeof_function(slang_atom a_name, const slang_operation * params,
770 GLuint num_params,
771 const slang_name_space * space,
772 slang_type_specifier * spec, GLboolean * exists,
773 slang_atom_pool *atoms, slang_info_log *log)
774 {
775 slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
776 num_params, space, atoms, log);
777 *exists = fun != NULL;
778 if (!fun)
779 return GL_TRUE; /* yes, not false */
780 return slang_type_specifier_copy(spec, &fun->header.type.specifier);
781 }
782
783
784
785 /**
786 * Determine if a type is a matrix.
787 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
788 */
789 GLboolean
790 _slang_type_is_matrix(slang_type_specifier_type ty)
791 {
792 switch (ty) {
793 case SLANG_SPEC_MAT2:
794 case SLANG_SPEC_MAT3:
795 case SLANG_SPEC_MAT4:
796 return GL_TRUE;
797 default:
798 return GL_FALSE;
799 }
800 }
801
802
803 /**
804 * Determine if a type is a vector.
805 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
806 */
807 GLboolean
808 _slang_type_is_vector(slang_type_specifier_type ty)
809 {
810 switch (ty) {
811 case SLANG_SPEC_VEC2:
812 case SLANG_SPEC_VEC3:
813 case SLANG_SPEC_VEC4:
814 case SLANG_SPEC_IVEC2:
815 case SLANG_SPEC_IVEC3:
816 case SLANG_SPEC_IVEC4:
817 case SLANG_SPEC_BVEC2:
818 case SLANG_SPEC_BVEC3:
819 case SLANG_SPEC_BVEC4:
820 return GL_TRUE;
821 default:
822 return GL_FALSE;
823 }
824 }
825
826
827 /**
828 * Given a vector type, return the type of the vector's elements
829 */
830 slang_type_specifier_type
831 _slang_type_base(slang_type_specifier_type ty)
832 {
833 switch (ty) {
834 case SLANG_SPEC_FLOAT:
835 case SLANG_SPEC_VEC2:
836 case SLANG_SPEC_VEC3:
837 case SLANG_SPEC_VEC4:
838 return SLANG_SPEC_FLOAT;
839 case SLANG_SPEC_INT:
840 case SLANG_SPEC_IVEC2:
841 case SLANG_SPEC_IVEC3:
842 case SLANG_SPEC_IVEC4:
843 return SLANG_SPEC_INT;
844 case SLANG_SPEC_BOOL:
845 case SLANG_SPEC_BVEC2:
846 case SLANG_SPEC_BVEC3:
847 case SLANG_SPEC_BVEC4:
848 return SLANG_SPEC_BOOL;
849 case SLANG_SPEC_MAT2:
850 return SLANG_SPEC_VEC2;
851 case SLANG_SPEC_MAT3:
852 return SLANG_SPEC_VEC3;
853 case SLANG_SPEC_MAT4:
854 return SLANG_SPEC_VEC4;
855 default:
856 return SLANG_SPEC_VOID;
857 }
858 }
859
860
861 /**
862 * Return the dimensionality of a vector or matrix type.
863 */
864 GLuint
865 _slang_type_dim(slang_type_specifier_type ty)
866 {
867 switch (ty) {
868 case SLANG_SPEC_FLOAT:
869 case SLANG_SPEC_INT:
870 case SLANG_SPEC_BOOL:
871 return 1;
872 case SLANG_SPEC_VEC2:
873 case SLANG_SPEC_IVEC2:
874 case SLANG_SPEC_BVEC2:
875 case SLANG_SPEC_MAT2:
876 return 2;
877 case SLANG_SPEC_VEC3:
878 case SLANG_SPEC_IVEC3:
879 case SLANG_SPEC_BVEC3:
880 case SLANG_SPEC_MAT3:
881 return 3;
882 case SLANG_SPEC_VEC4:
883 case SLANG_SPEC_IVEC4:
884 case SLANG_SPEC_BVEC4:
885 case SLANG_SPEC_MAT4:
886 return 4;
887 default:
888 return 0;
889 }
890 }