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