add _slang_multiply_swizzles()
[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 GLboolean
235 slang_type_specifier_equal(const slang_type_specifier * x,
236 const slang_type_specifier * y)
237 {
238 if (x->type != y->type)
239 return 0;
240 if (x->type == slang_spec_struct)
241 return slang_struct_equal(x->_struct, y->_struct);
242 if (x->type == slang_spec_array)
243 return slang_type_specifier_equal(x->_array, y->_array);
244 return 1;
245 }
246
247
248 GLboolean
249 slang_typeinfo_construct(slang_typeinfo * ti)
250 {
251 slang_type_specifier_ctr(&ti->spec);
252 ti->array_len = 0;
253 return GL_TRUE;
254 }
255
256 GLvoid
257 slang_typeinfo_destruct(slang_typeinfo * ti)
258 {
259 slang_type_specifier_dtr(&ti->spec);
260 }
261
262
263 /**
264 * Determine the return type of a function.
265 * \param name name of the function
266 * \param params array of function parameters
267 * \param num_params number of parameters
268 * \param space namespace to use
269 * \param spec returns the function's type
270 * \param atoms atom pool
271 * \return GL_TRUE for success, GL_FALSE if failure
272 */
273 static GLboolean
274 typeof_existing_function(const char *name, const slang_operation * params,
275 GLuint num_params,
276 const slang_name_space * space,
277 slang_type_specifier * spec,
278 slang_atom_pool * atoms)
279 {
280 slang_atom atom;
281 GLboolean exists;
282
283 atom = slang_atom_pool_atom(atoms, name);
284 if (!_slang_typeof_function(atom, params, num_params, space, spec,
285 &exists, atoms))
286 return GL_FALSE;
287 return exists;
288 }
289
290 GLboolean
291 _slang_typeof_operation(const slang_assemble_ctx * A,
292 const slang_operation * op,
293 slang_typeinfo * ti)
294 {
295 return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
296 }
297
298
299 /**
300 * Determine the return type of an operation.
301 * \param op the operation node
302 * \param space the namespace to use
303 * \param ti the returned type
304 * \param atoms atom pool
305 * \return GL_TRUE for success, GL_FALSE if failure
306 */
307 GLboolean
308 _slang_typeof_operation_(const slang_operation * op,
309 const slang_name_space * space,
310 slang_typeinfo * ti,
311 slang_atom_pool * atoms)
312 {
313 ti->can_be_referenced = GL_FALSE;
314 ti->is_swizzled = GL_FALSE;
315
316 switch (op->type) {
317 case slang_oper_block_no_new_scope:
318 case slang_oper_block_new_scope:
319 case slang_oper_variable_decl:
320 case slang_oper_asm:
321 case slang_oper_break:
322 case slang_oper_continue:
323 case slang_oper_discard:
324 case slang_oper_return:
325 case slang_oper_if:
326 case slang_oper_while:
327 case slang_oper_do:
328 case slang_oper_for:
329 case slang_oper_void:
330 ti->spec.type = slang_spec_void;
331 break;
332 case slang_oper_expression:
333 case slang_oper_assign:
334 case slang_oper_addassign:
335 case slang_oper_subassign:
336 case slang_oper_mulassign:
337 case slang_oper_divassign:
338 case slang_oper_preincrement:
339 case slang_oper_predecrement:
340 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
341 return GL_FALSE;
342 break;
343 case slang_oper_literal_bool:
344 case slang_oper_logicalor:
345 case slang_oper_logicalxor:
346 case slang_oper_logicaland:
347 case slang_oper_equal:
348 case slang_oper_notequal:
349 case slang_oper_less:
350 case slang_oper_greater:
351 case slang_oper_lessequal:
352 case slang_oper_greaterequal:
353 case slang_oper_not:
354 ti->spec.type = slang_spec_bool;
355 break;
356 case slang_oper_literal_int:
357 ti->spec.type = slang_spec_int;
358 break;
359 case slang_oper_literal_float:
360 ti->spec.type = slang_spec_float;
361 break;
362 case slang_oper_identifier:
363 {
364 slang_variable *var;
365 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
366 if (var == NULL)
367 RETURN_ERROR2("undefined variable", (char *) op->a_id, 0);
368 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
369 RETURN_OUT_OF_MEMORY();
370 ti->can_be_referenced = GL_TRUE;
371 ti->array_len = var->array_len;
372 }
373 break;
374 case slang_oper_sequence:
375 /* TODO: check [0] and [1] if they match */
376 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
377 RETURN_NIL();
378 ti->can_be_referenced = GL_FALSE;
379 ti->is_swizzled = GL_FALSE;
380 break;
381 /*case slang_oper_modassign: */
382 /*case slang_oper_lshassign: */
383 /*case slang_oper_rshassign: */
384 /*case slang_oper_orassign: */
385 /*case slang_oper_xorassign: */
386 /*case slang_oper_andassign: */
387 case slang_oper_select:
388 /* TODO: check [1] and [2] if they match */
389 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
390 RETURN_NIL();
391 ti->can_be_referenced = GL_FALSE;
392 ti->is_swizzled = GL_FALSE;
393 break;
394 /*case slang_oper_bitor: */
395 /*case slang_oper_bitxor: */
396 /*case slang_oper_bitand: */
397 /*case slang_oper_lshift: */
398 /*case slang_oper_rshift: */
399 case slang_oper_add:
400 if (!typeof_existing_function("+", op->children, 2, space,
401 &ti->spec, atoms))
402 RETURN_NIL();
403 break;
404 case slang_oper_subtract:
405 if (!typeof_existing_function("-", op->children, 2, space,
406 &ti->spec, atoms))
407 RETURN_NIL();
408 break;
409 case slang_oper_multiply:
410 if (!typeof_existing_function("*", op->children, 2, space,
411 &ti->spec, atoms))
412 RETURN_NIL();
413 break;
414 case slang_oper_divide:
415 if (!typeof_existing_function("/", op->children, 2, space,
416 &ti->spec, atoms))
417 RETURN_NIL();
418 break;
419 /*case slang_oper_modulus: */
420 case slang_oper_plus:
421 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
422 RETURN_NIL();
423 ti->can_be_referenced = GL_FALSE;
424 ti->is_swizzled = GL_FALSE;
425 break;
426 case slang_oper_minus:
427 if (!typeof_existing_function("-", op->children, 1, space,
428 &ti->spec, atoms))
429 RETURN_NIL();
430 break;
431 /*case slang_oper_complement: */
432 case slang_oper_subscript:
433 {
434 slang_typeinfo _ti;
435
436 if (!slang_typeinfo_construct(&_ti))
437 RETURN_NIL();
438 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
439 slang_typeinfo_destruct(&_ti);
440 RETURN_NIL();
441 }
442 ti->can_be_referenced = _ti.can_be_referenced;
443 if (_ti.spec.type == slang_spec_array) {
444 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
445 slang_typeinfo_destruct(&_ti);
446 RETURN_NIL();
447 }
448 }
449 else {
450 if (!_slang_type_is_vector(_ti.spec.type)
451 && !_slang_type_is_matrix(_ti.spec.type)) {
452 slang_typeinfo_destruct(&_ti);
453 RETURN_ERROR("cannot index a non-array type", 0);
454 }
455 ti->spec.type = _slang_type_base(_ti.spec.type);
456 }
457 slang_typeinfo_destruct(&_ti);
458 }
459 break;
460 case slang_oper_call:
461 {
462 GLboolean exists;
463
464 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
465 space, &ti->spec, &exists, atoms))
466 RETURN_NIL();
467 if (!exists) {
468 slang_struct *s =
469 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
470 if (s != NULL) {
471 ti->spec.type = slang_spec_struct;
472 ti->spec._struct =
473 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
474 if (ti->spec._struct == NULL)
475 RETURN_NIL();
476 if (!slang_struct_construct(ti->spec._struct)) {
477 slang_alloc_free(ti->spec._struct);
478 ti->spec._struct = NULL;
479 RETURN_NIL();
480 }
481 if (!slang_struct_copy(ti->spec._struct, s))
482 RETURN_NIL();
483 }
484 else {
485 const char *name;
486 slang_type_specifier_type type;
487
488 name = slang_atom_pool_id(atoms, op->a_id);
489 type = slang_type_specifier_type_from_string(name);
490 if (type == slang_spec_void)
491 RETURN_ERROR2("function not found", name, 0);
492 ti->spec.type = type;
493 }
494 }
495 }
496 break;
497 case slang_oper_field:
498 {
499 slang_typeinfo _ti;
500
501 if (!slang_typeinfo_construct(&_ti))
502 RETURN_NIL();
503 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
504 slang_typeinfo_destruct(&_ti);
505 RETURN_NIL();
506 }
507 if (_ti.spec.type == slang_spec_struct) {
508 slang_variable *field;
509
510 field = _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
511 GL_FALSE);
512 if (field == NULL) {
513 slang_typeinfo_destruct(&_ti);
514 RETURN_NIL();
515 }
516 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
517 slang_typeinfo_destruct(&_ti);
518 RETURN_NIL();
519 }
520 ti->can_be_referenced = _ti.can_be_referenced;
521 }
522 else {
523 GLuint rows;
524 const char *swizzle;
525 slang_type_specifier_type base;
526
527 /* determine the swizzle of the field expression */
528 #if 000
529 if (!_slang_type_is_vector(_ti.spec.type)) {
530 slang_typeinfo_destruct(&_ti);
531 RETURN_ERROR("Can't swizzle scalar expression", 0);
532 }
533 #endif
534 rows = _slang_type_dim(_ti.spec.type);
535 swizzle = slang_atom_pool_id(atoms, op->a_id);
536 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
537 slang_typeinfo_destruct(&_ti);
538 RETURN_ERROR("Bad swizzle", 0);
539 }
540 ti->is_swizzled = GL_TRUE;
541 ti->can_be_referenced = _ti.can_be_referenced
542 && _slang_is_swizzle_mask(&ti->swz, rows);
543 if (_ti.is_swizzled) {
544 slang_swizzle swz;
545
546 /* swizzle the swizzle */
547 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
548 ti->swz = swz;
549 }
550 base = _slang_type_base(_ti.spec.type);
551 switch (ti->swz.num_components) {
552 case 1:
553 ti->spec.type = base;
554 break;
555 case 2:
556 switch (base) {
557 case slang_spec_float:
558 ti->spec.type = slang_spec_vec2;
559 break;
560 case slang_spec_int:
561 ti->spec.type = slang_spec_ivec2;
562 break;
563 case slang_spec_bool:
564 ti->spec.type = slang_spec_bvec2;
565 break;
566 default:
567 break;
568 }
569 break;
570 case 3:
571 switch (base) {
572 case slang_spec_float:
573 ti->spec.type = slang_spec_vec3;
574 break;
575 case slang_spec_int:
576 ti->spec.type = slang_spec_ivec3;
577 break;
578 case slang_spec_bool:
579 ti->spec.type = slang_spec_bvec3;
580 break;
581 default:
582 break;
583 }
584 break;
585 case 4:
586 switch (base) {
587 case slang_spec_float:
588 ti->spec.type = slang_spec_vec4;
589 break;
590 case slang_spec_int:
591 ti->spec.type = slang_spec_ivec4;
592 break;
593 case slang_spec_bool:
594 ti->spec.type = slang_spec_bvec4;
595 break;
596 default:
597 break;
598 }
599 break;
600 default:
601 break;
602 }
603 }
604 slang_typeinfo_destruct(&_ti);
605 }
606 break;
607 case slang_oper_postincrement:
608 case slang_oper_postdecrement:
609 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
610 RETURN_NIL();
611 ti->can_be_referenced = GL_FALSE;
612 ti->is_swizzled = GL_FALSE;
613 break;
614 default:
615 RETURN_NIL();
616 }
617
618 return GL_TRUE;
619 }
620
621
622
623 slang_function *
624 _slang_locate_function(const slang_function_scope * funcs, slang_atom a_name,
625 const slang_operation * args, GLuint num_args,
626 const slang_name_space * space,
627 slang_atom_pool * atoms)
628 {
629 GLuint i;
630
631 for (i = 0; i < funcs->num_functions; i++) {
632 slang_function *f = &funcs->functions[i];
633 const GLuint haveRetValue = _slang_function_has_return_value(f);
634 GLuint j;
635
636 if (a_name != f->header.a_name)
637 continue;
638 if (f->param_count - haveRetValue != num_args)
639 continue;
640
641 /* compare parameter / argument types */
642 for (j = 0; j < num_args; j++) {
643 slang_typeinfo ti;
644
645 if (!slang_typeinfo_construct(&ti))
646 return NULL;
647 if (!_slang_typeof_operation_(&args[j], space, &ti, atoms)) {
648 slang_typeinfo_destruct(&ti);
649 return NULL;
650 }
651 if (!slang_type_specifier_equal(&ti.spec,
652 &f->parameters->variables[j/* + haveRetValue*/]->type.specifier)) {
653 slang_typeinfo_destruct(&ti);
654 break;
655 }
656 slang_typeinfo_destruct(&ti);
657
658 /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
659 if (!ti.can_be_referenced &&
660 (f->parameters->variables[j/* + haveRetValue*/]->type.qualifier == slang_qual_out ||
661 f->parameters->variables[j/* + haveRetValue*/]->type.qualifier == slang_qual_inout))
662 break;
663 }
664 if (j == num_args)
665 return f;
666 }
667 if (funcs->outer_scope != NULL)
668 return _slang_locate_function(funcs->outer_scope, a_name, args,
669 num_args, space, atoms);
670 return NULL;
671 }
672
673
674
675 /**
676 * Determine the return type of a function.
677 * \param a_name the function name
678 * \param param function parameters (overloading)
679 * \param num_params number of parameters to function
680 * \param space namespace to search
681 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
682 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
683 */
684 GLboolean
685 _slang_typeof_function(slang_atom a_name, const slang_operation * params,
686 GLuint num_params,
687 const slang_name_space * space,
688 slang_type_specifier * spec, GLboolean * exists,
689 slang_atom_pool * atoms)
690 {
691 slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
692 num_params, space, atoms);
693 *exists = fun != NULL;
694 if (!fun)
695 return GL_TRUE; /* yes, not false */
696 return slang_type_specifier_copy(spec, &fun->header.type.specifier);
697 }
698
699
700
701 /**
702 * Determine if a type is a matrix.
703 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
704 */
705 GLboolean
706 _slang_type_is_matrix(slang_type_specifier_type ty)
707 {
708 switch (ty) {
709 case slang_spec_mat2:
710 case slang_spec_mat3:
711 case slang_spec_mat4:
712 return GL_TRUE;
713 default:
714 return GL_FALSE;
715 }
716 }
717
718
719 /**
720 * Determine if a type is a vector.
721 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
722 */
723 GLboolean
724 _slang_type_is_vector(slang_type_specifier_type ty)
725 {
726 switch (ty) {
727 case slang_spec_vec2:
728 case slang_spec_vec3:
729 case slang_spec_vec4:
730 case slang_spec_ivec2:
731 case slang_spec_ivec3:
732 case slang_spec_ivec4:
733 case slang_spec_bvec2:
734 case slang_spec_bvec3:
735 case slang_spec_bvec4:
736 return GL_TRUE;
737 default:
738 return GL_FALSE;
739 }
740 }
741
742
743 /**
744 * Given a vector type, return the type of the vector's elements
745 */
746 slang_type_specifier_type
747 _slang_type_base(slang_type_specifier_type ty)
748 {
749 switch (ty) {
750 case slang_spec_float:
751 case slang_spec_vec2:
752 case slang_spec_vec3:
753 case slang_spec_vec4:
754 return slang_spec_float;
755 case slang_spec_int:
756 case slang_spec_ivec2:
757 case slang_spec_ivec3:
758 case slang_spec_ivec4:
759 return slang_spec_int;
760 case slang_spec_bool:
761 case slang_spec_bvec2:
762 case slang_spec_bvec3:
763 case slang_spec_bvec4:
764 return slang_spec_bool;
765 case slang_spec_mat2:
766 return slang_spec_vec2;
767 case slang_spec_mat3:
768 return slang_spec_vec3;
769 case slang_spec_mat4:
770 return slang_spec_vec4;
771 default:
772 return slang_spec_void;
773 }
774 }
775
776
777 /**
778 * Return the dimensionality of a vector or matrix type.
779 */
780 GLuint
781 _slang_type_dim(slang_type_specifier_type ty)
782 {
783 switch (ty) {
784 case slang_spec_float:
785 case slang_spec_int:
786 case slang_spec_bool:
787 return 1;
788 case slang_spec_vec2:
789 case slang_spec_ivec2:
790 case slang_spec_bvec2:
791 case slang_spec_mat2:
792 return 2;
793 case slang_spec_vec3:
794 case slang_spec_ivec3:
795 case slang_spec_bvec3:
796 case slang_spec_mat3:
797 return 3;
798 case slang_spec_vec4:
799 case slang_spec_ivec4:
800 case slang_spec_bvec4:
801 case slang_spec_mat4:
802 return 4;
803 default:
804 return 0;
805 }
806 }