2 * Mesa 3-D graphics library
5 * Copyright (C) 2005-2006 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 * \file slang_assemble_typeinfo.c
32 #include "slang_assemble.h"
33 #include "slang_compile.h"
34 #include "slang_error.h"
38 slang_type_specifier_ctr(slang_type_specifier
* self
)
40 self
->type
= slang_spec_void
;
46 slang_type_specifier_dtr(slang_type_specifier
* self
)
48 if (self
->_struct
!= NULL
) {
49 slang_struct_destruct(self
->_struct
);
50 slang_alloc_free(self
->_struct
);
52 if (self
->_array
!= NULL
) {
53 slang_type_specifier_dtr(self
->_array
);
54 slang_alloc_free(self
->_array
);
59 slang_type_specifier_copy(slang_type_specifier
* x
,
60 const slang_type_specifier
* y
)
62 slang_type_specifier z
;
64 slang_type_specifier_ctr(&z
);
66 if (z
.type
== slang_spec_struct
) {
67 z
._struct
= (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
68 if (z
._struct
== NULL
) {
69 slang_type_specifier_dtr(&z
);
72 if (!slang_struct_construct(z
._struct
)) {
73 slang_alloc_free(z
._struct
);
74 slang_type_specifier_dtr(&z
);
77 if (!slang_struct_copy(z
._struct
, y
->_struct
)) {
78 slang_type_specifier_dtr(&z
);
82 else if (z
.type
== slang_spec_array
) {
84 (slang_type_specifier
*)
85 slang_alloc_malloc(sizeof(slang_type_specifier
));
86 if (z
._array
== NULL
) {
87 slang_type_specifier_dtr(&z
);
90 slang_type_specifier_ctr(z
._array
);
91 if (!slang_type_specifier_copy(z
._array
, y
->_array
)) {
92 slang_type_specifier_dtr(&z
);
96 slang_type_specifier_dtr(x
);
102 slang_type_specifier_equal(const slang_type_specifier
* x
,
103 const slang_type_specifier
* y
)
105 if (x
->type
!= y
->type
)
107 if (x
->type
== slang_spec_struct
)
108 return slang_struct_equal(x
->_struct
, y
->_struct
);
109 if (x
->type
== slang_spec_array
)
110 return slang_type_specifier_equal(x
->_array
, y
->_array
);
116 slang_assembly_typeinfo_construct(slang_assembly_typeinfo
* ti
)
118 slang_type_specifier_ctr(&ti
->spec
);
124 slang_assembly_typeinfo_destruct(slang_assembly_typeinfo
* ti
)
126 slang_type_specifier_dtr(&ti
->spec
);
131 * Determine the return type of a function.
132 * \param name name of the function
133 * \param params array of function parameters
134 * \param num_params number of parameters
135 * \param space namespace to use
136 * \param spec returns the function's type
137 * \param atoms atom pool
138 * \return GL_TRUE for success, GL_FALSE if failure
141 typeof_existing_function(const char *name
, const slang_operation
* params
,
143 const slang_assembly_name_space
* space
,
144 slang_type_specifier
* spec
,
145 slang_atom_pool
* atoms
)
150 atom
= slang_atom_pool_atom(atoms
, name
);
151 if (!_slang_typeof_function(atom
, params
, num_params
, space
, spec
,
158 _slang_typeof_operation(const slang_assemble_ctx
* A
,
159 const slang_operation
* op
,
160 slang_assembly_typeinfo
* ti
)
162 return _slang_typeof_operation_(op
, &A
->space
, ti
, A
->atoms
);
167 * Determine the return type of an operation.
168 * \param op the operation node
169 * \param space the namespace to use
170 * \param ti the returned type
171 * \param atoms atom pool
172 * \return GL_TRUE for success, GL_FALSE if failure
175 _slang_typeof_operation_(const slang_operation
* op
,
176 const slang_assembly_name_space
* space
,
177 slang_assembly_typeinfo
* ti
,
178 slang_atom_pool
* atoms
)
180 ti
->can_be_referenced
= GL_FALSE
;
181 ti
->is_swizzled
= GL_FALSE
;
184 case slang_oper_block_no_new_scope
:
185 case slang_oper_block_new_scope
:
186 case slang_oper_variable_decl
:
188 case slang_oper_break
:
189 case slang_oper_continue
:
190 case slang_oper_discard
:
191 case slang_oper_return
:
193 case slang_oper_while
:
196 case slang_oper_void
:
197 ti
->spec
.type
= slang_spec_void
;
199 case slang_oper_expression
:
200 case slang_oper_assign
:
201 case slang_oper_addassign
:
202 case slang_oper_subassign
:
203 case slang_oper_mulassign
:
204 case slang_oper_divassign
:
205 case slang_oper_preincrement
:
206 case slang_oper_predecrement
:
207 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
210 case slang_oper_literal_bool
:
211 case slang_oper_logicalor
:
212 case slang_oper_logicalxor
:
213 case slang_oper_logicaland
:
214 case slang_oper_equal
:
215 case slang_oper_notequal
:
216 case slang_oper_less
:
217 case slang_oper_greater
:
218 case slang_oper_lessequal
:
219 case slang_oper_greaterequal
:
221 ti
->spec
.type
= slang_spec_bool
;
223 case slang_oper_literal_int
:
224 ti
->spec
.type
= slang_spec_int
;
226 case slang_oper_literal_float
:
227 ti
->spec
.type
= slang_spec_float
;
229 case slang_oper_identifier
:
232 var
= _slang_locate_variable(op
->locals
, op
->a_id
, GL_TRUE
);
234 RETURN_ERROR2("undefined variable", (char *) op
->a_id
, 0);
235 if (!slang_type_specifier_copy(&ti
->spec
, &var
->type
.specifier
))
236 RETURN_OUT_OF_MEMORY();
237 ti
->can_be_referenced
= GL_TRUE
;
238 ti
->array_len
= var
->array_len
;
241 case slang_oper_sequence
:
242 /* TODO: check [0] and [1] if they match */
243 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
))
245 ti
->can_be_referenced
= GL_FALSE
;
246 ti
->is_swizzled
= GL_FALSE
;
248 /*case slang_oper_modassign: */
249 /*case slang_oper_lshassign: */
250 /*case slang_oper_rshassign: */
251 /*case slang_oper_orassign: */
252 /*case slang_oper_xorassign: */
253 /*case slang_oper_andassign: */
254 case slang_oper_select
:
255 /* TODO: check [1] and [2] if they match */
256 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
))
258 ti
->can_be_referenced
= GL_FALSE
;
259 ti
->is_swizzled
= GL_FALSE
;
261 /*case slang_oper_bitor: */
262 /*case slang_oper_bitxor: */
263 /*case slang_oper_bitand: */
264 /*case slang_oper_lshift: */
265 /*case slang_oper_rshift: */
267 if (!typeof_existing_function("+", op
->children
, 2, space
,
271 case slang_oper_subtract
:
272 if (!typeof_existing_function("-", op
->children
, 2, space
,
276 case slang_oper_multiply
:
277 if (!typeof_existing_function("*", op
->children
, 2, space
,
281 case slang_oper_divide
:
282 if (!typeof_existing_function("/", op
->children
, 2, space
,
286 /*case slang_oper_modulus: */
287 case slang_oper_plus
:
288 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
290 ti
->can_be_referenced
= GL_FALSE
;
291 ti
->is_swizzled
= GL_FALSE
;
293 case slang_oper_minus
:
294 if (!typeof_existing_function("-", op
->children
, 1, space
,
298 /*case slang_oper_complement: */
299 case slang_oper_subscript
:
301 slang_assembly_typeinfo _ti
;
303 if (!slang_assembly_typeinfo_construct(&_ti
))
305 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
)) {
306 slang_assembly_typeinfo_destruct(&_ti
);
309 ti
->can_be_referenced
= _ti
.can_be_referenced
;
310 if (_ti
.spec
.type
== slang_spec_array
) {
311 if (!slang_type_specifier_copy(&ti
->spec
, _ti
.spec
._array
)) {
312 slang_assembly_typeinfo_destruct(&_ti
);
317 if (!_slang_type_is_vector(_ti
.spec
.type
)
318 && !_slang_type_is_matrix(_ti
.spec
.type
)) {
319 slang_assembly_typeinfo_destruct(&_ti
);
320 RETURN_ERROR("cannot index a non-array type", 0);
322 ti
->spec
.type
= _slang_type_base(_ti
.spec
.type
);
324 slang_assembly_typeinfo_destruct(&_ti
);
327 case slang_oper_call
:
331 if (!_slang_typeof_function(op
->a_id
, op
->children
, op
->num_children
,
332 space
, &ti
->spec
, &exists
, atoms
))
336 slang_struct_scope_find(space
->structs
, op
->a_id
, GL_TRUE
);
338 ti
->spec
.type
= slang_spec_struct
;
340 (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
341 if (ti
->spec
._struct
== NULL
)
343 if (!slang_struct_construct(ti
->spec
._struct
)) {
344 slang_alloc_free(ti
->spec
._struct
);
345 ti
->spec
._struct
= NULL
;
348 if (!slang_struct_copy(ti
->spec
._struct
, s
))
353 slang_type_specifier_type type
;
355 name
= slang_atom_pool_id(atoms
, op
->a_id
);
356 type
= slang_type_specifier_type_from_string(name
);
357 if (type
== slang_spec_void
)
358 RETURN_ERROR2("function not found", name
, 0);
359 ti
->spec
.type
= type
;
364 case slang_oper_field
:
366 slang_assembly_typeinfo _ti
;
368 if (!slang_assembly_typeinfo_construct(&_ti
))
370 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
)) {
371 slang_assembly_typeinfo_destruct(&_ti
);
374 if (_ti
.spec
.type
== slang_spec_struct
) {
375 slang_variable
*field
;
377 field
= _slang_locate_variable(_ti
.spec
._struct
->fields
, op
->a_id
,
380 slang_assembly_typeinfo_destruct(&_ti
);
383 if (!slang_type_specifier_copy(&ti
->spec
, &field
->type
.specifier
)) {
384 slang_assembly_typeinfo_destruct(&_ti
);
387 ti
->can_be_referenced
= _ti
.can_be_referenced
;
392 slang_type_specifier_type base
;
394 /* determine the swizzle of the field expression */
396 if (!_slang_type_is_vector(_ti
.spec
.type
)) {
397 slang_assembly_typeinfo_destruct(&_ti
);
398 RETURN_ERROR("Can't swizzle scalar expression", 0);
401 rows
= _slang_type_dim(_ti
.spec
.type
);
402 swizzle
= slang_atom_pool_id(atoms
, op
->a_id
);
403 if (!_slang_is_swizzle(swizzle
, rows
, &ti
->swz
)) {
404 slang_assembly_typeinfo_destruct(&_ti
);
405 RETURN_ERROR("Bad swizzle", 0);
407 ti
->is_swizzled
= GL_TRUE
;
408 ti
->can_be_referenced
= _ti
.can_be_referenced
409 && _slang_is_swizzle_mask(&ti
->swz
, rows
);
410 if (_ti
.is_swizzled
) {
413 /* swizzle the swizzle */
414 _slang_multiply_swizzles(&swz
, &_ti
.swz
, &ti
->swz
);
417 base
= _slang_type_base(_ti
.spec
.type
);
418 switch (ti
->swz
.num_components
) {
420 ti
->spec
.type
= base
;
424 case slang_spec_float
:
425 ti
->spec
.type
= slang_spec_vec2
;
428 ti
->spec
.type
= slang_spec_ivec2
;
430 case slang_spec_bool
:
431 ti
->spec
.type
= slang_spec_bvec2
;
439 case slang_spec_float
:
440 ti
->spec
.type
= slang_spec_vec3
;
443 ti
->spec
.type
= slang_spec_ivec3
;
445 case slang_spec_bool
:
446 ti
->spec
.type
= slang_spec_bvec3
;
454 case slang_spec_float
:
455 ti
->spec
.type
= slang_spec_vec4
;
458 ti
->spec
.type
= slang_spec_ivec4
;
460 case slang_spec_bool
:
461 ti
->spec
.type
= slang_spec_bvec4
;
471 slang_assembly_typeinfo_destruct(&_ti
);
474 case slang_oper_postincrement
:
475 case slang_oper_postdecrement
:
476 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
478 ti
->can_be_referenced
= GL_FALSE
;
479 ti
->is_swizzled
= GL_FALSE
;
491 * Determine the return type of a function.
492 * \param a_name the function name
493 * \param param function parameters (overloading)
494 * \param num_params number of parameters to function
495 * \param space namespace to search
496 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
497 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
500 _slang_typeof_function(slang_atom a_name
, const slang_operation
* params
,
502 const slang_assembly_name_space
* space
,
503 slang_type_specifier
* spec
, GLboolean
* exists
,
504 slang_atom_pool
* atoms
)
506 slang_function
*fun
= _slang_locate_function(space
->funcs
, a_name
, params
,
507 num_params
, space
, atoms
);
508 *exists
= fun
!= NULL
;
510 return GL_TRUE
; /* yes, not false */
511 return slang_type_specifier_copy(spec
, &fun
->header
.type
.specifier
);
517 * Determine if a type is a matrix.
518 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
521 _slang_type_is_matrix(slang_type_specifier_type ty
)
524 case slang_spec_mat2
:
525 case slang_spec_mat3
:
526 case slang_spec_mat4
:
535 * Determine if a type is a vector.
536 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
539 _slang_type_is_vector(slang_type_specifier_type ty
)
542 case slang_spec_vec2
:
543 case slang_spec_vec3
:
544 case slang_spec_vec4
:
545 case slang_spec_ivec2
:
546 case slang_spec_ivec3
:
547 case slang_spec_ivec4
:
548 case slang_spec_bvec2
:
549 case slang_spec_bvec3
:
550 case slang_spec_bvec4
:
559 * Given a vector type, return the type of the vector's elements
561 slang_type_specifier_type
562 _slang_type_base(slang_type_specifier_type ty
)
565 case slang_spec_float
:
566 case slang_spec_vec2
:
567 case slang_spec_vec3
:
568 case slang_spec_vec4
:
569 return slang_spec_float
;
571 case slang_spec_ivec2
:
572 case slang_spec_ivec3
:
573 case slang_spec_ivec4
:
574 return slang_spec_int
;
575 case slang_spec_bool
:
576 case slang_spec_bvec2
:
577 case slang_spec_bvec3
:
578 case slang_spec_bvec4
:
579 return slang_spec_bool
;
580 case slang_spec_mat2
:
581 return slang_spec_vec2
;
582 case slang_spec_mat3
:
583 return slang_spec_vec3
;
584 case slang_spec_mat4
:
585 return slang_spec_vec4
;
587 return slang_spec_void
;
593 * Return the dimensionality of a vector or matrix type.
596 _slang_type_dim(slang_type_specifier_type ty
)
599 case slang_spec_float
:
601 case slang_spec_bool
:
603 case slang_spec_vec2
:
604 case slang_spec_ivec2
:
605 case slang_spec_bvec2
:
606 case slang_spec_mat2
:
608 case slang_spec_vec3
:
609 case slang_spec_ivec3
:
610 case slang_spec_bvec3
:
611 case slang_spec_mat3
:
613 case slang_spec_vec4
:
614 case slang_spec_ivec4
:
615 case slang_spec_bvec4
:
616 case slang_spec_mat4
: