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"
36 * slang_type_specifier
40 slang_type_specifier_ctr(slang_type_specifier
* self
)
42 self
->type
= slang_spec_void
;
48 slang_type_specifier_dtr(slang_type_specifier
* self
)
50 if (self
->_struct
!= NULL
) {
51 slang_struct_destruct(self
->_struct
);
52 slang_alloc_free(self
->_struct
);
54 if (self
->_array
!= NULL
) {
55 slang_type_specifier_dtr(self
->_array
);
56 slang_alloc_free(self
->_array
);
61 slang_type_specifier_copy(slang_type_specifier
* x
,
62 const slang_type_specifier
* y
)
64 slang_type_specifier z
;
66 slang_type_specifier_ctr(&z
);
68 if (z
.type
== slang_spec_struct
) {
69 z
._struct
= (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
70 if (z
._struct
== NULL
) {
71 slang_type_specifier_dtr(&z
);
74 if (!slang_struct_construct(z
._struct
)) {
75 slang_alloc_free(z
._struct
);
76 slang_type_specifier_dtr(&z
);
79 if (!slang_struct_copy(z
._struct
, y
->_struct
)) {
80 slang_type_specifier_dtr(&z
);
84 else if (z
.type
== slang_spec_array
) {
86 (slang_type_specifier
*)
87 slang_alloc_malloc(sizeof(slang_type_specifier
));
88 if (z
._array
== NULL
) {
89 slang_type_specifier_dtr(&z
);
92 slang_type_specifier_ctr(z
._array
);
93 if (!slang_type_specifier_copy(z
._array
, y
->_array
)) {
94 slang_type_specifier_dtr(&z
);
98 slang_type_specifier_dtr(x
);
104 slang_type_specifier_equal(const slang_type_specifier
* x
,
105 const slang_type_specifier
* y
)
107 if (x
->type
!= y
->type
)
109 if (x
->type
== slang_spec_struct
)
110 return slang_struct_equal(x
->_struct
, y
->_struct
);
111 if (x
->type
== slang_spec_array
)
112 return slang_type_specifier_equal(x
->_array
, y
->_array
);
116 /* slang_assembly_typeinfo */
119 slang_assembly_typeinfo_construct(slang_assembly_typeinfo
* ti
)
121 slang_type_specifier_ctr(&ti
->spec
);
127 slang_assembly_typeinfo_destruct(slang_assembly_typeinfo
* ti
)
129 slang_type_specifier_dtr(&ti
->spec
);
132 /* _slang_typeof_operation() */
135 typeof_existing_function(const char *name
, slang_operation
* params
,
136 GLuint num_params
, slang_assembly_name_space
* space
,
137 slang_type_specifier
* spec
, slang_atom_pool
* atoms
)
142 atom
= slang_atom_pool_atom(atoms
, name
);
143 if (!_slang_typeof_function
144 (atom
, params
, num_params
, space
, spec
, &exists
, atoms
))
150 _slang_typeof_operation(slang_assemble_ctx
* A
, slang_operation
* op
,
151 slang_assembly_typeinfo
* ti
)
153 return _slang_typeof_operation_(op
, &A
->space
, ti
, A
->atoms
);
157 _slang_typeof_operation_(slang_operation
* op
,
158 slang_assembly_name_space
* space
,
159 slang_assembly_typeinfo
* ti
,
160 slang_atom_pool
* atoms
)
162 ti
->can_be_referenced
= GL_FALSE
;
163 ti
->is_swizzled
= GL_FALSE
;
166 case slang_oper_block_no_new_scope
:
167 case slang_oper_block_new_scope
:
168 case slang_oper_variable_decl
:
170 case slang_oper_break
:
171 case slang_oper_continue
:
172 case slang_oper_discard
:
173 case slang_oper_return
:
175 case slang_oper_while
:
178 case slang_oper_void
:
179 ti
->spec
.type
= slang_spec_void
;
181 case slang_oper_expression
:
182 case slang_oper_assign
:
183 case slang_oper_addassign
:
184 case slang_oper_subassign
:
185 case slang_oper_mulassign
:
186 case slang_oper_divassign
:
187 case slang_oper_preincrement
:
188 case slang_oper_predecrement
:
189 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
192 case slang_oper_literal_bool
:
193 case slang_oper_logicalor
:
194 case slang_oper_logicalxor
:
195 case slang_oper_logicaland
:
196 case slang_oper_equal
:
197 case slang_oper_notequal
:
198 case slang_oper_less
:
199 case slang_oper_greater
:
200 case slang_oper_lessequal
:
201 case slang_oper_greaterequal
:
203 ti
->spec
.type
= slang_spec_bool
;
205 case slang_oper_literal_int
:
206 ti
->spec
.type
= slang_spec_int
;
208 case slang_oper_literal_float
:
209 ti
->spec
.type
= slang_spec_float
;
211 case slang_oper_identifier
:
215 var
= _slang_locate_variable(op
->locals
, op
->a_id
, GL_TRUE
);
218 if (!slang_type_specifier_copy(&ti
->spec
, &var
->type
.specifier
))
220 ti
->can_be_referenced
= GL_TRUE
;
221 ti
->array_len
= var
->array_len
;
224 case slang_oper_sequence
:
225 /* TODO: check [0] and [1] if they match */
226 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
))
228 ti
->can_be_referenced
= GL_FALSE
;
229 ti
->is_swizzled
= GL_FALSE
;
231 /*case slang_oper_modassign: */
232 /*case slang_oper_lshassign: */
233 /*case slang_oper_rshassign: */
234 /*case slang_oper_orassign: */
235 /*case slang_oper_xorassign: */
236 /*case slang_oper_andassign: */
237 case slang_oper_select
:
238 /* TODO: check [1] and [2] if they match */
239 if (!_slang_typeof_operation_(&op
->children
[1], space
, ti
, atoms
))
241 ti
->can_be_referenced
= GL_FALSE
;
242 ti
->is_swizzled
= GL_FALSE
;
244 /*case slang_oper_bitor: */
245 /*case slang_oper_bitxor: */
246 /*case slang_oper_bitand: */
247 /*case slang_oper_lshift: */
248 /*case slang_oper_rshift: */
250 if (!typeof_existing_function
251 ("+", op
->children
, 2, space
, &ti
->spec
, atoms
))
254 case slang_oper_subtract
:
255 if (!typeof_existing_function
256 ("-", op
->children
, 2, space
, &ti
->spec
, atoms
))
259 case slang_oper_multiply
:
260 if (!typeof_existing_function
261 ("*", op
->children
, 2, space
, &ti
->spec
, atoms
))
264 case slang_oper_divide
:
265 if (!typeof_existing_function
266 ("/", op
->children
, 2, space
, &ti
->spec
, atoms
))
269 /*case slang_oper_modulus: */
270 case slang_oper_plus
:
271 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
273 ti
->can_be_referenced
= GL_FALSE
;
274 ti
->is_swizzled
= GL_FALSE
;
276 case slang_oper_minus
:
277 if (!typeof_existing_function
278 ("-", op
->children
, 1, space
, &ti
->spec
, atoms
))
281 /*case slang_oper_complement: */
282 case slang_oper_subscript
:
284 slang_assembly_typeinfo _ti
;
286 if (!slang_assembly_typeinfo_construct(&_ti
))
288 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
)) {
289 slang_assembly_typeinfo_destruct(&_ti
);
292 ti
->can_be_referenced
= _ti
.can_be_referenced
;
293 if (_ti
.spec
.type
== slang_spec_array
) {
294 if (!slang_type_specifier_copy(&ti
->spec
, _ti
.spec
._array
)) {
295 slang_assembly_typeinfo_destruct(&_ti
);
300 if (!_slang_type_is_vector(_ti
.spec
.type
)
301 && !_slang_type_is_matrix(_ti
.spec
.type
)) {
302 slang_assembly_typeinfo_destruct(&_ti
);
305 ti
->spec
.type
= _slang_type_base(_ti
.spec
.type
);
307 slang_assembly_typeinfo_destruct(&_ti
);
310 case slang_oper_call
:
314 if (!_slang_typeof_function
315 (op
->a_id
, op
->children
, op
->num_children
, space
, &ti
->spec
,
320 slang_struct_scope_find(space
->structs
, op
->a_id
, GL_TRUE
);
322 ti
->spec
.type
= slang_spec_struct
;
324 (slang_struct
*) slang_alloc_malloc(sizeof(slang_struct
));
325 if (ti
->spec
._struct
== NULL
)
327 if (!slang_struct_construct(ti
->spec
._struct
)) {
328 slang_alloc_free(ti
->spec
._struct
);
329 ti
->spec
._struct
= NULL
;
332 if (!slang_struct_copy(ti
->spec
._struct
, s
))
337 slang_type_specifier_type type
;
339 name
= slang_atom_pool_id(atoms
, op
->a_id
);
340 type
= slang_type_specifier_type_from_string(name
);
341 if (type
== slang_spec_void
)
343 ti
->spec
.type
= type
;
348 case slang_oper_field
:
350 slang_assembly_typeinfo _ti
;
352 if (!slang_assembly_typeinfo_construct(&_ti
))
354 if (!_slang_typeof_operation_(op
->children
, space
, &_ti
, atoms
)) {
355 slang_assembly_typeinfo_destruct(&_ti
);
358 if (_ti
.spec
.type
== slang_spec_struct
) {
359 slang_variable
*field
;
362 _slang_locate_variable(_ti
.spec
._struct
->fields
, op
->a_id
,
365 slang_assembly_typeinfo_destruct(&_ti
);
368 if (!slang_type_specifier_copy(&ti
->spec
, &field
->type
.specifier
)) {
369 slang_assembly_typeinfo_destruct(&_ti
);
372 ti
->can_be_referenced
= _ti
.can_be_referenced
;
377 slang_type_specifier_type base
;
379 /* determine the swizzle of the field expression */
380 if (!_slang_type_is_vector(_ti
.spec
.type
)) {
381 slang_assembly_typeinfo_destruct(&_ti
);
384 rows
= _slang_type_dim(_ti
.spec
.type
);
385 swizzle
= slang_atom_pool_id(atoms
, op
->a_id
);
386 if (!_slang_is_swizzle(swizzle
, rows
, &ti
->swz
)) {
387 slang_assembly_typeinfo_destruct(&_ti
);
390 ti
->is_swizzled
= GL_TRUE
;
391 ti
->can_be_referenced
= _ti
.can_be_referenced
392 && _slang_is_swizzle_mask(&ti
->swz
, rows
);
393 if (_ti
.is_swizzled
) {
396 /* swizzle the swizzle */
397 _slang_multiply_swizzles(&swz
, &_ti
.swz
, &ti
->swz
);
400 base
= _slang_type_base(_ti
.spec
.type
);
401 switch (ti
->swz
.num_components
) {
403 ti
->spec
.type
= base
;
407 case slang_spec_float
:
408 ti
->spec
.type
= slang_spec_vec2
;
411 ti
->spec
.type
= slang_spec_ivec2
;
413 case slang_spec_bool
:
414 ti
->spec
.type
= slang_spec_bvec2
;
422 case slang_spec_float
:
423 ti
->spec
.type
= slang_spec_vec3
;
426 ti
->spec
.type
= slang_spec_ivec3
;
428 case slang_spec_bool
:
429 ti
->spec
.type
= slang_spec_bvec3
;
437 case slang_spec_float
:
438 ti
->spec
.type
= slang_spec_vec4
;
441 ti
->spec
.type
= slang_spec_ivec4
;
443 case slang_spec_bool
:
444 ti
->spec
.type
= slang_spec_bvec4
;
454 slang_assembly_typeinfo_destruct(&_ti
);
457 case slang_oper_postincrement
:
458 case slang_oper_postdecrement
:
459 if (!_slang_typeof_operation_(op
->children
, space
, ti
, atoms
))
461 ti
->can_be_referenced
= GL_FALSE
;
462 ti
->is_swizzled
= GL_FALSE
;
471 /* _slang_typeof_function() */
474 _slang_typeof_function(slang_atom a_name
, slang_operation
* params
,
475 GLuint num_params
, slang_assembly_name_space
* space
,
476 slang_type_specifier
* spec
, GLboolean
* exists
,
477 slang_atom_pool
* atoms
)
482 _slang_locate_function(space
->funcs
, a_name
, params
, num_params
, space
,
484 *exists
= fun
!= NULL
;
487 return slang_type_specifier_copy(spec
, &fun
->header
.type
.specifier
);
490 /* _slang_type_is_matrix() */
493 _slang_type_is_matrix(slang_type_specifier_type ty
)
496 case slang_spec_mat2
:
497 case slang_spec_mat3
:
498 case slang_spec_mat4
:
505 /* _slang_type_is_vector() */
508 _slang_type_is_vector(slang_type_specifier_type ty
)
511 case slang_spec_vec2
:
512 case slang_spec_vec3
:
513 case slang_spec_vec4
:
514 case slang_spec_ivec2
:
515 case slang_spec_ivec3
:
516 case slang_spec_ivec4
:
517 case slang_spec_bvec2
:
518 case slang_spec_bvec3
:
519 case slang_spec_bvec4
:
526 /* _slang_type_base_of_vector() */
528 slang_type_specifier_type
529 _slang_type_base(slang_type_specifier_type ty
)
532 case slang_spec_float
:
533 case slang_spec_vec2
:
534 case slang_spec_vec3
:
535 case slang_spec_vec4
:
536 return slang_spec_float
;
538 case slang_spec_ivec2
:
539 case slang_spec_ivec3
:
540 case slang_spec_ivec4
:
541 return slang_spec_int
;
542 case slang_spec_bool
:
543 case slang_spec_bvec2
:
544 case slang_spec_bvec3
:
545 case slang_spec_bvec4
:
546 return slang_spec_bool
;
547 case slang_spec_mat2
:
548 return slang_spec_vec2
;
549 case slang_spec_mat3
:
550 return slang_spec_vec3
;
551 case slang_spec_mat4
:
552 return slang_spec_vec4
;
554 return slang_spec_void
;
558 /* _slang_type_dim */
561 _slang_type_dim(slang_type_specifier_type ty
)
564 case slang_spec_float
:
566 case slang_spec_bool
:
568 case slang_spec_vec2
:
569 case slang_spec_ivec2
:
570 case slang_spec_bvec2
:
571 case slang_spec_mat2
:
573 case slang_spec_vec3
:
574 case slang_spec_ivec3
:
575 case slang_spec_bvec3
:
576 case slang_spec_mat3
:
578 case slang_spec_vec4
:
579 case slang_spec_ivec4
:
580 case slang_spec_bvec4
:
581 case slang_spec_mat4
: