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