OSDN Git Service

r600g: add POW instruction
[android-x86/external-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 "program/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