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_utility.h"
33 #include "slang_assemble_typeinfo.h"
35 /* slang_assembly_typeinfo */
37 int slang_assembly_typeinfo_construct (slang_assembly_typeinfo
*ti
)
39 if (!slang_type_specifier_construct (&ti
->spec
))
41 ti
->array_size
= NULL
;
45 void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo
*ti
)
47 slang_type_specifier_destruct (&ti
->spec
);
48 /* do not free ti->array_size */
51 /* _slang_typeof_operation() */
53 static int typeof_existing_function (const char *name
, slang_operation
*params
,
54 unsigned int num_params
, slang_assembly_name_space
*space
, slang_type_specifier
*spec
,
55 slang_atom_pool
*atoms
)
60 atom
= slang_atom_pool_atom (atoms
, name
);
61 if (!_slang_typeof_function (atom
, params
, num_params
, space
, spec
, &exists
, atoms
))
66 int _slang_typeof_operation (slang_operation
*op
, slang_assembly_name_space
*space
,
67 slang_assembly_typeinfo
*ti
, slang_atom_pool
*atoms
)
69 ti
->can_be_referenced
= 0;
74 case slang_oper_block_no_new_scope
:
75 case slang_oper_block_new_scope
:
76 case slang_oper_variable_decl
:
78 case slang_oper_break
:
79 case slang_oper_continue
:
80 case slang_oper_discard
:
81 case slang_oper_return
:
83 case slang_oper_while
:
87 ti
->spec
.type
= slang_spec_void
;
89 case slang_oper_expression
:
90 case slang_oper_assign
:
91 case slang_oper_addassign
:
92 case slang_oper_subassign
:
93 case slang_oper_mulassign
:
94 case slang_oper_divassign
:
95 case slang_oper_preincrement
:
96 case slang_oper_predecrement
:
97 if (!_slang_typeof_operation (op
->children
, space
, ti
, atoms
))
100 case slang_oper_literal_bool
:
101 case slang_oper_logicalor
:
102 case slang_oper_logicalxor
:
103 case slang_oper_logicaland
:
104 case slang_oper_equal
:
105 case slang_oper_notequal
:
106 case slang_oper_less
:
107 case slang_oper_greater
:
108 case slang_oper_lessequal
:
109 case slang_oper_greaterequal
:
111 ti
->spec
.type
= slang_spec_bool
;
113 case slang_oper_literal_int
:
114 ti
->spec
.type
= slang_spec_int
;
116 case slang_oper_literal_float
:
117 ti
->spec
.type
= slang_spec_float
;
119 case slang_oper_identifier
:
123 var
= _slang_locate_variable (op
->locals
, op
->a_id
, 1);
126 if (!slang_type_specifier_copy (&ti
->spec
, &var
->type
.specifier
))
128 ti
->can_be_referenced
= 1;
129 ti
->array_size
= var
->array_size
;
132 case slang_oper_sequence
:
133 /* TODO: check [0] and [1] if they match */
134 if (!_slang_typeof_operation (&op
->children
[1], space
, ti
, atoms
))
136 ti
->can_be_referenced
= 0;
139 /*case slang_oper_modassign:*/
140 /*case slang_oper_lshassign:*/
141 /*case slang_oper_rshassign:*/
142 /*case slang_oper_orassign:*/
143 /*case slang_oper_xorassign:*/
144 /*case slang_oper_andassign:*/
145 case slang_oper_select
:
146 /* TODO: check [1] and [2] if they match */
147 if (!_slang_typeof_operation (&op
->children
[1], space
, ti
, atoms
))
149 ti
->can_be_referenced
= 0;
152 /*case slang_oper_bitor:*/
153 /*case slang_oper_bitxor:*/
154 /*case slang_oper_bitand:*/
155 /*case slang_oper_lshift:*/
156 /*case slang_oper_rshift:*/
158 if (!typeof_existing_function ("+", op
->children
, 2, space
, &ti
->spec
, atoms
))
161 case slang_oper_subtract
:
162 if (!typeof_existing_function ("-", op
->children
, 2, space
, &ti
->spec
, atoms
))
165 case slang_oper_multiply
:
166 if (!typeof_existing_function ("*", op
->children
, 2, space
, &ti
->spec
, atoms
))
169 case slang_oper_divide
:
170 if (!typeof_existing_function ("/", op
->children
, 2, space
, &ti
->spec
, atoms
))
173 /*case slang_oper_modulus:*/
174 case slang_oper_plus
:
175 if (!_slang_typeof_operation (op
->children
, space
, ti
, atoms
))
177 ti
->can_be_referenced
= 0;
180 case slang_oper_minus
:
181 if (!typeof_existing_function ("-", op
->children
, 1, space
, &ti
->spec
, atoms
))
184 /*case slang_oper_complement:*/
185 case slang_oper_subscript
:
187 slang_assembly_typeinfo _ti
;
189 if (!slang_assembly_typeinfo_construct (&_ti
))
191 if (!_slang_typeof_operation (op
->children
, space
, &_ti
, atoms
))
193 slang_assembly_typeinfo_destruct (&_ti
);
196 ti
->can_be_referenced
= _ti
.can_be_referenced
;
197 if (_ti
.spec
.type
== slang_spec_array
)
199 if (!slang_type_specifier_copy (&ti
->spec
, _ti
.spec
._array
))
201 slang_assembly_typeinfo_destruct (&_ti
);
207 if (!_slang_type_is_vector (_ti
.spec
.type
) && !_slang_type_is_matrix (_ti
.spec
.type
))
209 slang_assembly_typeinfo_destruct (&_ti
);
212 ti
->spec
.type
= _slang_type_base (_ti
.spec
.type
);
214 slang_assembly_typeinfo_destruct (&_ti
);
217 case slang_oper_call
:
221 if (!_slang_typeof_function (op
->a_id
, op
->children
, op
->num_children
, space
, &ti
->spec
,
226 /* slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1);
229 ti->spec.type = slang_spec_struct;
230 ti->spec._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
231 if (ti->spec._struct == NULL)
233 if (!slang_struct_construct (ti->spec._struct))
235 slang_alloc_free (ti->spec._struct);
236 ti->spec._struct = NULL;
239 if (!slang_struct_copy (ti->spec._struct, s))
245 slang_type_specifier_type type
;
247 name
= slang_atom_pool_id (atoms
, op
->a_id
);
248 type
= slang_type_specifier_type_from_string (name
);
249 if (type
== slang_spec_void
)
251 ti
->spec
.type
= type
;
256 case slang_oper_field
:
258 slang_assembly_typeinfo _ti
;
260 if (!slang_assembly_typeinfo_construct (&_ti
))
262 if (!_slang_typeof_operation (op
->children
, space
, &_ti
, atoms
))
264 slang_assembly_typeinfo_destruct (&_ti
);
267 if (_ti
.spec
.type
== slang_spec_struct
)
269 slang_variable
*field
;
271 field
= _slang_locate_variable (_ti
.spec
._struct
->fields
, op
->a_id
, 0);
274 slang_assembly_typeinfo_destruct (&_ti
);
277 if (!slang_type_specifier_copy (&ti
->spec
, &field
->type
.specifier
))
279 slang_assembly_typeinfo_destruct (&_ti
);
282 ti
->can_be_referenced
= _ti
.can_be_referenced
;
288 slang_type_specifier_type base
;
290 /* determine the swizzle of the field expression */
291 if (!_slang_type_is_vector (_ti
.spec
.type
))
293 slang_assembly_typeinfo_destruct (&_ti
);
296 rows
= _slang_type_dim (_ti
.spec
.type
);
297 swizzle
= slang_atom_pool_id (atoms
, op
->a_id
);
298 if (!_slang_is_swizzle (swizzle
, rows
, &ti
->swz
))
300 slang_assembly_typeinfo_destruct (&_ti
);
304 ti
->can_be_referenced
= _ti
.can_be_referenced
&& _slang_is_swizzle_mask (&ti
->swz
,
310 /* swizzle the swizzle */
311 _slang_multiply_swizzles (&swz
, &_ti
.swz
, &ti
->swz
);
314 base
= _slang_type_base (_ti
.spec
.type
);
315 switch (ti
->swz
.num_components
)
318 ti
->spec
.type
= base
;
323 case slang_spec_float
:
324 ti
->spec
.type
= slang_spec_vec2
;
327 ti
->spec
.type
= slang_spec_ivec2
;
329 case slang_spec_bool
:
330 ti
->spec
.type
= slang_spec_bvec2
;
333 _mesa_problem(NULL
, "unexepected base in _slang_typeof_operation");
334 ti
->spec
.type
= slang_spec_void
;
340 case slang_spec_float
:
341 ti
->spec
.type
= slang_spec_vec3
;
344 ti
->spec
.type
= slang_spec_ivec3
;
346 case slang_spec_bool
:
347 ti
->spec
.type
= slang_spec_bvec3
;
350 _mesa_problem(NULL
, "unexepected base in _slang_typeof_operation");
351 ti
->spec
.type
= slang_spec_void
;
357 case slang_spec_float
:
358 ti
->spec
.type
= slang_spec_vec4
;
361 ti
->spec
.type
= slang_spec_ivec4
;
363 case slang_spec_bool
:
364 ti
->spec
.type
= slang_spec_bvec4
;
367 _mesa_problem(NULL
, "unexepected base in _slang_typeof_operation");
368 ti
->spec
.type
= slang_spec_void
;
375 slang_assembly_typeinfo_destruct (&_ti
);
378 case slang_oper_postincrement
:
379 case slang_oper_postdecrement
:
380 if (!_slang_typeof_operation (op
->children
, space
, ti
, atoms
))
382 ti
->can_be_referenced
= 0;
391 /* _slang_typeof_function() */
393 int _slang_typeof_function (slang_atom a_name
, slang_operation
*params
, unsigned int num_params
,
394 slang_assembly_name_space
*space
, slang_type_specifier
*spec
, int *exists
, slang_atom_pool
*atoms
)
398 fun
= _slang_locate_function (space
->funcs
, a_name
, params
, num_params
, space
, atoms
);
399 *exists
= fun
!= NULL
;
402 return slang_type_specifier_copy (spec
, &fun
->header
.type
.specifier
);
405 /* _slang_type_is_matrix() */
407 int _slang_type_is_matrix (slang_type_specifier_type ty
)
411 case slang_spec_mat2
:
412 case slang_spec_mat3
:
413 case slang_spec_mat4
:
420 /* _slang_type_is_vector() */
422 int _slang_type_is_vector (slang_type_specifier_type ty
)
426 case slang_spec_vec2
:
427 case slang_spec_vec3
:
428 case slang_spec_vec4
:
429 case slang_spec_ivec2
:
430 case slang_spec_ivec3
:
431 case slang_spec_ivec4
:
432 case slang_spec_bvec2
:
433 case slang_spec_bvec3
:
434 case slang_spec_bvec4
:
441 /* _slang_type_base_of_vector() */
443 slang_type_specifier_type
_slang_type_base (slang_type_specifier_type ty
)
447 case slang_spec_float
:
448 case slang_spec_vec2
:
449 case slang_spec_vec3
:
450 case slang_spec_vec4
:
451 return slang_spec_float
;
453 case slang_spec_ivec2
:
454 case slang_spec_ivec3
:
455 case slang_spec_ivec4
:
456 return slang_spec_int
;
457 case slang_spec_bool
:
458 case slang_spec_bvec2
:
459 case slang_spec_bvec3
:
460 case slang_spec_bvec4
:
461 return slang_spec_bool
;
462 case slang_spec_mat2
:
463 return slang_spec_vec2
;
464 case slang_spec_mat3
:
465 return slang_spec_vec3
;
466 case slang_spec_mat4
:
467 return slang_spec_vec4
;
469 return slang_spec_void
;
473 /* _slang_type_dim */
475 unsigned int _slang_type_dim (slang_type_specifier_type ty
)
479 case slang_spec_float
:
481 case slang_spec_bool
:
483 case slang_spec_vec2
:
484 case slang_spec_ivec2
:
485 case slang_spec_bvec2
:
486 case slang_spec_mat2
:
488 case slang_spec_vec3
:
489 case slang_spec_ivec3
:
490 case slang_spec_bvec3
:
491 case slang_spec_mat3
:
493 case slang_spec_vec4
:
494 case slang_spec_ivec4
:
495 case slang_spec_bvec4
:
496 case slang_spec_mat4
: