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