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