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