Add a lot of const qualifiers for const-correctness.
[mesa.git] / src / mesa / shader / slang / slang_assemble_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_assemble_typeinfo.c
27 * slang type info
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_assemble.h"
33 #include "slang_compile.h"
34
35 /*
36 * slang_type_specifier
37 */
38
39 GLvoid
40 slang_type_specifier_ctr(slang_type_specifier * self)
41 {
42 self->type = slang_spec_void;
43 self->_struct = NULL;
44 self->_array = NULL;
45 }
46
47 GLvoid
48 slang_type_specifier_dtr(slang_type_specifier * self)
49 {
50 if (self->_struct != NULL) {
51 slang_struct_destruct(self->_struct);
52 slang_alloc_free(self->_struct);
53 }
54 if (self->_array != NULL) {
55 slang_type_specifier_dtr(self->_array);
56 slang_alloc_free(self->_array);
57 }
58 }
59
60 GLboolean
61 slang_type_specifier_copy(slang_type_specifier * x,
62 const slang_type_specifier * y)
63 {
64 slang_type_specifier z;
65
66 slang_type_specifier_ctr(&z);
67 z.type = y->type;
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);
72 return GL_FALSE;
73 }
74 if (!slang_struct_construct(z._struct)) {
75 slang_alloc_free(z._struct);
76 slang_type_specifier_dtr(&z);
77 return GL_FALSE;
78 }
79 if (!slang_struct_copy(z._struct, y->_struct)) {
80 slang_type_specifier_dtr(&z);
81 return GL_FALSE;
82 }
83 }
84 else if (z.type == slang_spec_array) {
85 z._array =
86 (slang_type_specifier *)
87 slang_alloc_malloc(sizeof(slang_type_specifier));
88 if (z._array == NULL) {
89 slang_type_specifier_dtr(&z);
90 return GL_FALSE;
91 }
92 slang_type_specifier_ctr(z._array);
93 if (!slang_type_specifier_copy(z._array, y->_array)) {
94 slang_type_specifier_dtr(&z);
95 return GL_FALSE;
96 }
97 }
98 slang_type_specifier_dtr(x);
99 *x = z;
100 return GL_TRUE;
101 }
102
103 GLboolean
104 slang_type_specifier_equal(const slang_type_specifier * x,
105 const slang_type_specifier * y)
106 {
107 if (x->type != y->type)
108 return 0;
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);
113 return 1;
114 }
115
116 /* slang_assembly_typeinfo */
117
118 GLboolean
119 slang_assembly_typeinfo_construct(slang_assembly_typeinfo * ti)
120 {
121 slang_type_specifier_ctr(&ti->spec);
122 ti->array_len = 0;
123 return GL_TRUE;
124 }
125
126 GLvoid
127 slang_assembly_typeinfo_destruct(slang_assembly_typeinfo * ti)
128 {
129 slang_type_specifier_dtr(&ti->spec);
130 }
131
132 /* _slang_typeof_operation() */
133
134 /**
135 * Determine the return type of a function.
136 * \param name name of the function
137 * \param params array of function parameters
138 * \param num_params number of parameters
139 * \param space namespace to use
140 * \param spec returns the function's type
141 * \param atoms atom pool
142 * \return GL_TRUE for success, GL_FALSE if failure
143 */
144 static GLboolean
145 typeof_existing_function(const char *name, const slang_operation * params,
146 GLuint num_params,
147 const slang_assembly_name_space * space,
148 slang_type_specifier * spec,
149 slang_atom_pool * atoms)
150 {
151 slang_atom atom;
152 GLboolean exists;
153
154 atom = slang_atom_pool_atom(atoms, name);
155 if (!_slang_typeof_function(atom, params, num_params, space, spec,
156 &exists, atoms))
157 return GL_FALSE;
158 return exists;
159 }
160
161 GLboolean
162 _slang_typeof_operation(const slang_assemble_ctx * A,
163 const slang_operation * op,
164 slang_assembly_typeinfo * ti)
165 {
166 return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
167 }
168
169
170 /**
171 * Determine the return type of an operation.
172 * \param op the operation node
173 * \param space the namespace to use
174 * \param ti the returned type
175 * \param atoms atom pool
176 * \return GL_TRUE for success, GL_FALSE if failure
177 */
178 GLboolean
179 _slang_typeof_operation_(const slang_operation * op,
180 const slang_assembly_name_space * space,
181 slang_assembly_typeinfo * ti,
182 slang_atom_pool * atoms)
183 {
184 ti->can_be_referenced = GL_FALSE;
185 ti->is_swizzled = GL_FALSE;
186
187 switch (op->type) {
188 case slang_oper_block_no_new_scope:
189 case slang_oper_block_new_scope:
190 case slang_oper_variable_decl:
191 case slang_oper_asm:
192 case slang_oper_break:
193 case slang_oper_continue:
194 case slang_oper_discard:
195 case slang_oper_return:
196 case slang_oper_if:
197 case slang_oper_while:
198 case slang_oper_do:
199 case slang_oper_for:
200 case slang_oper_void:
201 ti->spec.type = slang_spec_void;
202 break;
203 case slang_oper_expression:
204 case slang_oper_assign:
205 case slang_oper_addassign:
206 case slang_oper_subassign:
207 case slang_oper_mulassign:
208 case slang_oper_divassign:
209 case slang_oper_preincrement:
210 case slang_oper_predecrement:
211 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
212 return 0;
213 break;
214 case slang_oper_literal_bool:
215 case slang_oper_logicalor:
216 case slang_oper_logicalxor:
217 case slang_oper_logicaland:
218 case slang_oper_equal:
219 case slang_oper_notequal:
220 case slang_oper_less:
221 case slang_oper_greater:
222 case slang_oper_lessequal:
223 case slang_oper_greaterequal:
224 case slang_oper_not:
225 ti->spec.type = slang_spec_bool;
226 break;
227 case slang_oper_literal_int:
228 ti->spec.type = slang_spec_int;
229 break;
230 case slang_oper_literal_float:
231 ti->spec.type = slang_spec_float;
232 break;
233 case slang_oper_identifier:
234 {
235 slang_variable *var;
236
237 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
238 if (var == NULL)
239 return GL_FALSE;
240 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
241 return GL_FALSE;
242 ti->can_be_referenced = GL_TRUE;
243 ti->array_len = var->array_len;
244 }
245 break;
246 case slang_oper_sequence:
247 /* TODO: check [0] and [1] if they match */
248 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
249 return GL_FALSE;
250 ti->can_be_referenced = GL_FALSE;
251 ti->is_swizzled = GL_FALSE;
252 break;
253 /*case slang_oper_modassign: */
254 /*case slang_oper_lshassign: */
255 /*case slang_oper_rshassign: */
256 /*case slang_oper_orassign: */
257 /*case slang_oper_xorassign: */
258 /*case slang_oper_andassign: */
259 case slang_oper_select:
260 /* TODO: check [1] and [2] if they match */
261 if (!_slang_typeof_operation_(&op->children[1], space, ti, atoms))
262 return GL_FALSE;
263 ti->can_be_referenced = GL_FALSE;
264 ti->is_swizzled = GL_FALSE;
265 break;
266 /*case slang_oper_bitor: */
267 /*case slang_oper_bitxor: */
268 /*case slang_oper_bitand: */
269 /*case slang_oper_lshift: */
270 /*case slang_oper_rshift: */
271 case slang_oper_add:
272 if (!typeof_existing_function("+", op->children, 2, space,
273 &ti->spec, atoms))
274 return GL_FALSE;
275 break;
276 case slang_oper_subtract:
277 if (!typeof_existing_function("-", op->children, 2, space,
278 &ti->spec, atoms))
279 return GL_FALSE;
280 break;
281 case slang_oper_multiply:
282 if (!typeof_existing_function("*", op->children, 2, space,
283 &ti->spec, atoms))
284 return GL_FALSE;
285 break;
286 case slang_oper_divide:
287 if (!typeof_existing_function("/", op->children, 2, space,
288 &ti->spec, atoms))
289 return GL_FALSE;
290 break;
291 /*case slang_oper_modulus: */
292 case slang_oper_plus:
293 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
294 return GL_FALSE;
295 ti->can_be_referenced = GL_FALSE;
296 ti->is_swizzled = GL_FALSE;
297 break;
298 case slang_oper_minus:
299 if (!typeof_existing_function
300 ("-", op->children, 1, space, &ti->spec, atoms))
301 return GL_FALSE;
302 break;
303 /*case slang_oper_complement: */
304 case slang_oper_subscript:
305 {
306 slang_assembly_typeinfo _ti;
307
308 if (!slang_assembly_typeinfo_construct(&_ti))
309 return GL_FALSE;
310 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
311 slang_assembly_typeinfo_destruct(&_ti);
312 return GL_FALSE;
313 }
314 ti->can_be_referenced = _ti.can_be_referenced;
315 if (_ti.spec.type == slang_spec_array) {
316 if (!slang_type_specifier_copy(&ti->spec, _ti.spec._array)) {
317 slang_assembly_typeinfo_destruct(&_ti);
318 return GL_FALSE;
319 }
320 }
321 else {
322 if (!_slang_type_is_vector(_ti.spec.type)
323 && !_slang_type_is_matrix(_ti.spec.type)) {
324 slang_assembly_typeinfo_destruct(&_ti);
325 return GL_FALSE;
326 }
327 ti->spec.type = _slang_type_base(_ti.spec.type);
328 }
329 slang_assembly_typeinfo_destruct(&_ti);
330 }
331 break;
332 case slang_oper_call:
333 {
334 GLboolean exists;
335
336 if (!_slang_typeof_function(op->a_id, op->children, op->num_children,
337 space, &ti->spec, &exists, atoms))
338 return GL_FALSE;
339 if (!exists) {
340 slang_struct *s =
341 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
342 if (s != NULL) {
343 ti->spec.type = slang_spec_struct;
344 ti->spec._struct =
345 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
346 if (ti->spec._struct == NULL)
347 return GL_FALSE;
348 if (!slang_struct_construct(ti->spec._struct)) {
349 slang_alloc_free(ti->spec._struct);
350 ti->spec._struct = NULL;
351 return GL_FALSE;
352 }
353 if (!slang_struct_copy(ti->spec._struct, s))
354 return GL_FALSE;
355 }
356 else {
357 const char *name;
358 slang_type_specifier_type type;
359
360 name = slang_atom_pool_id(atoms, op->a_id);
361 type = slang_type_specifier_type_from_string(name);
362 if (type == slang_spec_void)
363 return GL_FALSE;
364 ti->spec.type = type;
365 }
366 }
367 }
368 break;
369 case slang_oper_field:
370 {
371 slang_assembly_typeinfo _ti;
372
373 if (!slang_assembly_typeinfo_construct(&_ti))
374 return GL_FALSE;
375 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
376 slang_assembly_typeinfo_destruct(&_ti);
377 return GL_FALSE;
378 }
379 if (_ti.spec.type == slang_spec_struct) {
380 slang_variable *field;
381
382 field =
383 _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
384 GL_FALSE);
385 if (field == NULL) {
386 slang_assembly_typeinfo_destruct(&_ti);
387 return GL_FALSE;
388 }
389 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
390 slang_assembly_typeinfo_destruct(&_ti);
391 return GL_FALSE;
392 }
393 ti->can_be_referenced = _ti.can_be_referenced;
394 }
395 else {
396 GLuint rows;
397 const char *swizzle;
398 slang_type_specifier_type base;
399
400 /* determine the swizzle of the field expression */
401 if (!_slang_type_is_vector(_ti.spec.type)) {
402 slang_assembly_typeinfo_destruct(&_ti);
403 return GL_FALSE;
404 }
405 rows = _slang_type_dim(_ti.spec.type);
406 swizzle = slang_atom_pool_id(atoms, op->a_id);
407 if (!_slang_is_swizzle(swizzle, rows, &ti->swz)) {
408 slang_assembly_typeinfo_destruct(&_ti);
409 return GL_FALSE;
410 }
411 ti->is_swizzled = GL_TRUE;
412 ti->can_be_referenced = _ti.can_be_referenced
413 && _slang_is_swizzle_mask(&ti->swz, rows);
414 if (_ti.is_swizzled) {
415 slang_swizzle swz;
416
417 /* swizzle the swizzle */
418 _slang_multiply_swizzles(&swz, &_ti.swz, &ti->swz);
419 ti->swz = swz;
420 }
421 base = _slang_type_base(_ti.spec.type);
422 switch (ti->swz.num_components) {
423 case 1:
424 ti->spec.type = base;
425 break;
426 case 2:
427 switch (base) {
428 case slang_spec_float:
429 ti->spec.type = slang_spec_vec2;
430 break;
431 case slang_spec_int:
432 ti->spec.type = slang_spec_ivec2;
433 break;
434 case slang_spec_bool:
435 ti->spec.type = slang_spec_bvec2;
436 break;
437 default:
438 break;
439 }
440 break;
441 case 3:
442 switch (base) {
443 case slang_spec_float:
444 ti->spec.type = slang_spec_vec3;
445 break;
446 case slang_spec_int:
447 ti->spec.type = slang_spec_ivec3;
448 break;
449 case slang_spec_bool:
450 ti->spec.type = slang_spec_bvec3;
451 break;
452 default:
453 break;
454 }
455 break;
456 case 4:
457 switch (base) {
458 case slang_spec_float:
459 ti->spec.type = slang_spec_vec4;
460 break;
461 case slang_spec_int:
462 ti->spec.type = slang_spec_ivec4;
463 break;
464 case slang_spec_bool:
465 ti->spec.type = slang_spec_bvec4;
466 break;
467 default:
468 break;
469 }
470 break;
471 default:
472 break;
473 }
474 }
475 slang_assembly_typeinfo_destruct(&_ti);
476 }
477 break;
478 case slang_oper_postincrement:
479 case slang_oper_postdecrement:
480 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
481 return GL_FALSE;
482 ti->can_be_referenced = GL_FALSE;
483 ti->is_swizzled = GL_FALSE;
484 break;
485 default:
486 return GL_FALSE;
487 }
488
489 return GL_TRUE;
490 }
491
492
493
494 /**
495 * Determine the return type of a function.
496 * \param a_name the function name
497 * \param param function parameters (overloading)
498 * \param num_params number of parameters to function
499 * \param space namespace to search
500 * \param exists returns GL_TRUE or GL_FALSE to indicate existance of function
501 * \return GL_TRUE for success, GL_FALSE if failure (bad function name)
502 */
503 GLboolean
504 _slang_typeof_function(slang_atom a_name, const slang_operation * params,
505 GLuint num_params,
506 const slang_assembly_name_space * space,
507 slang_type_specifier * spec, GLboolean * exists,
508 slang_atom_pool * atoms)
509 {
510 slang_function *fun = _slang_locate_function(space->funcs, a_name, params,
511 num_params, space, atoms);
512 *exists = fun != NULL;
513 if (!fun)
514 return GL_TRUE; /* yes, not false */
515 return slang_type_specifier_copy(spec, &fun->header.type.specifier);
516 }
517
518
519
520 /**
521 * Determine if a type is a matrix.
522 * \return GL_TRUE if is a matrix, GL_FALSE otherwise.
523 */
524 GLboolean
525 _slang_type_is_matrix(slang_type_specifier_type ty)
526 {
527 switch (ty) {
528 case slang_spec_mat2:
529 case slang_spec_mat3:
530 case slang_spec_mat4:
531 return GL_TRUE;
532 default:
533 return GL_FALSE;
534 }
535 }
536
537
538 /**
539 * Determine if a type is a vector.
540 * \return GL_TRUE if is a vector, GL_FALSE otherwise.
541 */
542 GLboolean
543 _slang_type_is_vector(slang_type_specifier_type ty)
544 {
545 switch (ty) {
546 case slang_spec_vec2:
547 case slang_spec_vec3:
548 case slang_spec_vec4:
549 case slang_spec_ivec2:
550 case slang_spec_ivec3:
551 case slang_spec_ivec4:
552 case slang_spec_bvec2:
553 case slang_spec_bvec3:
554 case slang_spec_bvec4:
555 return GL_TRUE;
556 default:
557 return GL_FALSE;
558 }
559 }
560
561
562 /**
563 * Given a vector type, return the type of the vector's elements
564 */
565 slang_type_specifier_type
566 _slang_type_base(slang_type_specifier_type ty)
567 {
568 switch (ty) {
569 case slang_spec_float:
570 case slang_spec_vec2:
571 case slang_spec_vec3:
572 case slang_spec_vec4:
573 return slang_spec_float;
574 case slang_spec_int:
575 case slang_spec_ivec2:
576 case slang_spec_ivec3:
577 case slang_spec_ivec4:
578 return slang_spec_int;
579 case slang_spec_bool:
580 case slang_spec_bvec2:
581 case slang_spec_bvec3:
582 case slang_spec_bvec4:
583 return slang_spec_bool;
584 case slang_spec_mat2:
585 return slang_spec_vec2;
586 case slang_spec_mat3:
587 return slang_spec_vec3;
588 case slang_spec_mat4:
589 return slang_spec_vec4;
590 default:
591 return slang_spec_void;
592 }
593 }
594
595
596 /**
597 * Return the number of elements in a vector or matrix type
598 */
599 GLuint
600 _slang_type_dim(slang_type_specifier_type ty)
601 {
602 switch (ty) {
603 case slang_spec_float:
604 case slang_spec_int:
605 case slang_spec_bool:
606 return 1;
607 case slang_spec_vec2:
608 case slang_spec_ivec2:
609 case slang_spec_bvec2:
610 case slang_spec_mat2:
611 return 2;
612 case slang_spec_vec3:
613 case slang_spec_ivec3:
614 case slang_spec_bvec3:
615 case slang_spec_mat3:
616 return 3;
617 case slang_spec_vec4:
618 case slang_spec_ivec4:
619 case slang_spec_bvec4:
620 case slang_spec_mat4:
621 return 4;
622 default:
623 return 0;
624 }
625 }