reindent
[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 static GLboolean
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)
138 {
139 slang_atom atom;
140 GLboolean exists;
141
142 atom = slang_atom_pool_atom(atoms, name);
143 if (!_slang_typeof_function
144 (atom, params, num_params, space, spec, &exists, atoms))
145 return GL_FALSE;
146 return exists;
147 }
148
149 GLboolean
150 _slang_typeof_operation(slang_assemble_ctx * A, slang_operation * op,
151 slang_assembly_typeinfo * ti)
152 {
153 return _slang_typeof_operation_(op, &A->space, ti, A->atoms);
154 }
155
156 GLboolean
157 _slang_typeof_operation_(slang_operation * op,
158 slang_assembly_name_space * space,
159 slang_assembly_typeinfo * ti,
160 slang_atom_pool * atoms)
161 {
162 ti->can_be_referenced = GL_FALSE;
163 ti->is_swizzled = GL_FALSE;
164
165 switch (op->type) {
166 case slang_oper_block_no_new_scope:
167 case slang_oper_block_new_scope:
168 case slang_oper_variable_decl:
169 case slang_oper_asm:
170 case slang_oper_break:
171 case slang_oper_continue:
172 case slang_oper_discard:
173 case slang_oper_return:
174 case slang_oper_if:
175 case slang_oper_while:
176 case slang_oper_do:
177 case slang_oper_for:
178 case slang_oper_void:
179 ti->spec.type = slang_spec_void;
180 break;
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))
190 return 0;
191 break;
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:
202 case slang_oper_not:
203 ti->spec.type = slang_spec_bool;
204 break;
205 case slang_oper_literal_int:
206 ti->spec.type = slang_spec_int;
207 break;
208 case slang_oper_literal_float:
209 ti->spec.type = slang_spec_float;
210 break;
211 case slang_oper_identifier:
212 {
213 slang_variable *var;
214
215 var = _slang_locate_variable(op->locals, op->a_id, GL_TRUE);
216 if (var == NULL)
217 return GL_FALSE;
218 if (!slang_type_specifier_copy(&ti->spec, &var->type.specifier))
219 return GL_FALSE;
220 ti->can_be_referenced = GL_TRUE;
221 ti->array_len = var->array_len;
222 }
223 break;
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))
227 return GL_FALSE;
228 ti->can_be_referenced = GL_FALSE;
229 ti->is_swizzled = GL_FALSE;
230 break;
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))
240 return GL_FALSE;
241 ti->can_be_referenced = GL_FALSE;
242 ti->is_swizzled = GL_FALSE;
243 break;
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: */
249 case slang_oper_add:
250 if (!typeof_existing_function
251 ("+", op->children, 2, space, &ti->spec, atoms))
252 return GL_FALSE;
253 break;
254 case slang_oper_subtract:
255 if (!typeof_existing_function
256 ("-", op->children, 2, space, &ti->spec, atoms))
257 return GL_FALSE;
258 break;
259 case slang_oper_multiply:
260 if (!typeof_existing_function
261 ("*", op->children, 2, space, &ti->spec, atoms))
262 return GL_FALSE;
263 break;
264 case slang_oper_divide:
265 if (!typeof_existing_function
266 ("/", op->children, 2, space, &ti->spec, atoms))
267 return GL_FALSE;
268 break;
269 /*case slang_oper_modulus: */
270 case slang_oper_plus:
271 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
272 return GL_FALSE;
273 ti->can_be_referenced = GL_FALSE;
274 ti->is_swizzled = GL_FALSE;
275 break;
276 case slang_oper_minus:
277 if (!typeof_existing_function
278 ("-", op->children, 1, space, &ti->spec, atoms))
279 return GL_FALSE;
280 break;
281 /*case slang_oper_complement: */
282 case slang_oper_subscript:
283 {
284 slang_assembly_typeinfo _ti;
285
286 if (!slang_assembly_typeinfo_construct(&_ti))
287 return GL_FALSE;
288 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
289 slang_assembly_typeinfo_destruct(&_ti);
290 return GL_FALSE;
291 }
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);
296 return GL_FALSE;
297 }
298 }
299 else {
300 if (!_slang_type_is_vector(_ti.spec.type)
301 && !_slang_type_is_matrix(_ti.spec.type)) {
302 slang_assembly_typeinfo_destruct(&_ti);
303 return GL_FALSE;
304 }
305 ti->spec.type = _slang_type_base(_ti.spec.type);
306 }
307 slang_assembly_typeinfo_destruct(&_ti);
308 }
309 break;
310 case slang_oper_call:
311 {
312 GLboolean exists;
313
314 if (!_slang_typeof_function
315 (op->a_id, op->children, op->num_children, space, &ti->spec,
316 &exists, atoms))
317 return GL_FALSE;
318 if (!exists) {
319 slang_struct *s =
320 slang_struct_scope_find(space->structs, op->a_id, GL_TRUE);
321 if (s != NULL) {
322 ti->spec.type = slang_spec_struct;
323 ti->spec._struct =
324 (slang_struct *) slang_alloc_malloc(sizeof(slang_struct));
325 if (ti->spec._struct == NULL)
326 return GL_FALSE;
327 if (!slang_struct_construct(ti->spec._struct)) {
328 slang_alloc_free(ti->spec._struct);
329 ti->spec._struct = NULL;
330 return GL_FALSE;
331 }
332 if (!slang_struct_copy(ti->spec._struct, s))
333 return GL_FALSE;
334 }
335 else {
336 const char *name;
337 slang_type_specifier_type type;
338
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)
342 return GL_FALSE;
343 ti->spec.type = type;
344 }
345 }
346 }
347 break;
348 case slang_oper_field:
349 {
350 slang_assembly_typeinfo _ti;
351
352 if (!slang_assembly_typeinfo_construct(&_ti))
353 return GL_FALSE;
354 if (!_slang_typeof_operation_(op->children, space, &_ti, atoms)) {
355 slang_assembly_typeinfo_destruct(&_ti);
356 return GL_FALSE;
357 }
358 if (_ti.spec.type == slang_spec_struct) {
359 slang_variable *field;
360
361 field =
362 _slang_locate_variable(_ti.spec._struct->fields, op->a_id,
363 GL_FALSE);
364 if (field == NULL) {
365 slang_assembly_typeinfo_destruct(&_ti);
366 return GL_FALSE;
367 }
368 if (!slang_type_specifier_copy(&ti->spec, &field->type.specifier)) {
369 slang_assembly_typeinfo_destruct(&_ti);
370 return GL_FALSE;
371 }
372 ti->can_be_referenced = _ti.can_be_referenced;
373 }
374 else {
375 GLuint rows;
376 const char *swizzle;
377 slang_type_specifier_type base;
378
379 /* determine the swizzle of the field expression */
380 if (!_slang_type_is_vector(_ti.spec.type)) {
381 slang_assembly_typeinfo_destruct(&_ti);
382 return GL_FALSE;
383 }
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);
388 return GL_FALSE;
389 }
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) {
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 case 1:
403 ti->spec.type = base;
404 break;
405 case 2:
406 switch (base) {
407 case slang_spec_float:
408 ti->spec.type = slang_spec_vec2;
409 break;
410 case slang_spec_int:
411 ti->spec.type = slang_spec_ivec2;
412 break;
413 case slang_spec_bool:
414 ti->spec.type = slang_spec_bvec2;
415 break;
416 default:
417 break;
418 }
419 break;
420 case 3:
421 switch (base) {
422 case slang_spec_float:
423 ti->spec.type = slang_spec_vec3;
424 break;
425 case slang_spec_int:
426 ti->spec.type = slang_spec_ivec3;
427 break;
428 case slang_spec_bool:
429 ti->spec.type = slang_spec_bvec3;
430 break;
431 default:
432 break;
433 }
434 break;
435 case 4:
436 switch (base) {
437 case slang_spec_float:
438 ti->spec.type = slang_spec_vec4;
439 break;
440 case slang_spec_int:
441 ti->spec.type = slang_spec_ivec4;
442 break;
443 case slang_spec_bool:
444 ti->spec.type = slang_spec_bvec4;
445 break;
446 default:
447 break;
448 }
449 break;
450 default:
451 break;
452 }
453 }
454 slang_assembly_typeinfo_destruct(&_ti);
455 }
456 break;
457 case slang_oper_postincrement:
458 case slang_oper_postdecrement:
459 if (!_slang_typeof_operation_(op->children, space, ti, atoms))
460 return GL_FALSE;
461 ti->can_be_referenced = GL_FALSE;
462 ti->is_swizzled = GL_FALSE;
463 break;
464 default:
465 return GL_FALSE;
466 }
467
468 return GL_TRUE;
469 }
470
471 /* _slang_typeof_function() */
472
473 GLboolean
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)
478 {
479 slang_function *fun;
480
481 fun =
482 _slang_locate_function(space->funcs, a_name, params, num_params, space,
483 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
493 _slang_type_is_matrix(slang_type_specifier_type ty)
494 {
495 switch (ty) {
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
508 _slang_type_is_vector(slang_type_specifier_type ty)
509 {
510 switch (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:
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
529 _slang_type_base(slang_type_specifier_type ty)
530 {
531 switch (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;
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
561 _slang_type_dim(slang_type_specifier_type ty)
562 {
563 switch (ty) {
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 }