Fix a few warnings:
[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_utility.h"
33 #include "slang_assemble_typeinfo.h"
34
35 /* slang_assembly_typeinfo */
36
37 int slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti)
38 {
39 if (!slang_type_specifier_construct (&ti->spec))
40 return 0;
41 ti->array_size = NULL;
42 return 1;
43 }
44
45 void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti)
46 {
47 slang_type_specifier_destruct (&ti->spec);
48 /* do not free ti->array_size */
49 }
50
51 /* _slang_typeof_operation() */
52
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)
56 {
57 slang_atom atom;
58 int exists;
59
60 atom = slang_atom_pool_atom (atoms, name);
61 if (!_slang_typeof_function (atom, params, num_params, space, spec, &exists, atoms))
62 return 0;
63 return exists;
64 }
65
66 int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *space,
67 slang_assembly_typeinfo *ti, slang_atom_pool *atoms)
68 {
69 ti->can_be_referenced = 0;
70 ti->is_swizzled = 0;
71
72 switch (op->type)
73 {
74 case slang_oper_block_no_new_scope:
75 case slang_oper_block_new_scope:
76 case slang_oper_variable_decl:
77 case slang_oper_asm:
78 case slang_oper_break:
79 case slang_oper_continue:
80 case slang_oper_discard:
81 case slang_oper_return:
82 case slang_oper_if:
83 case slang_oper_while:
84 case slang_oper_do:
85 case slang_oper_for:
86 case slang_oper_void:
87 ti->spec.type = slang_spec_void;
88 break;
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))
98 return 0;
99 break;
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:
110 case slang_oper_not:
111 ti->spec.type = slang_spec_bool;
112 break;
113 case slang_oper_literal_int:
114 ti->spec.type = slang_spec_int;
115 break;
116 case slang_oper_literal_float:
117 ti->spec.type = slang_spec_float;
118 break;
119 case slang_oper_identifier:
120 {
121 slang_variable *var;
122
123 var = _slang_locate_variable (op->locals, op->a_id, 1);
124 if (var == NULL)
125 return 0;
126 if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier))
127 return 0;
128 ti->can_be_referenced = 1;
129 ti->array_size = var->array_size;
130 }
131 break;
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))
135 return 0;
136 ti->can_be_referenced = 0;
137 ti->is_swizzled = 0;
138 break;
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))
148 return 0;
149 ti->can_be_referenced = 0;
150 ti->is_swizzled = 0;
151 break;
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:*/
157 case slang_oper_add:
158 if (!typeof_existing_function ("+", op->children, 2, space, &ti->spec, atoms))
159 return 0;
160 break;
161 case slang_oper_subtract:
162 if (!typeof_existing_function ("-", op->children, 2, space, &ti->spec, atoms))
163 return 0;
164 break;
165 case slang_oper_multiply:
166 if (!typeof_existing_function ("*", op->children, 2, space, &ti->spec, atoms))
167 return 0;
168 break;
169 case slang_oper_divide:
170 if (!typeof_existing_function ("/", op->children, 2, space, &ti->spec, atoms))
171 return 0;
172 break;
173 /*case slang_oper_modulus:*/
174 case slang_oper_plus:
175 if (!_slang_typeof_operation (op->children, space, ti, atoms))
176 return 0;
177 ti->can_be_referenced = 0;
178 ti->is_swizzled = 0;
179 break;
180 case slang_oper_minus:
181 if (!typeof_existing_function ("-", op->children, 1, space, &ti->spec, atoms))
182 return 0;
183 break;
184 /*case slang_oper_complement:*/
185 case slang_oper_subscript:
186 {
187 slang_assembly_typeinfo _ti;
188
189 if (!slang_assembly_typeinfo_construct (&_ti))
190 return 0;
191 if (!_slang_typeof_operation (op->children, space, &_ti, atoms))
192 {
193 slang_assembly_typeinfo_destruct (&_ti);
194 return 0;
195 }
196 ti->can_be_referenced = _ti.can_be_referenced;
197 if (_ti.spec.type == slang_spec_array)
198 {
199 if (!slang_type_specifier_copy (&ti->spec, _ti.spec._array))
200 {
201 slang_assembly_typeinfo_destruct (&_ti);
202 return 0;
203 }
204 }
205 else
206 {
207 if (!_slang_type_is_vector (_ti.spec.type) && !_slang_type_is_matrix (_ti.spec.type))
208 {
209 slang_assembly_typeinfo_destruct (&_ti);
210 return 0;
211 }
212 ti->spec.type = _slang_type_base (_ti.spec.type);
213 }
214 slang_assembly_typeinfo_destruct (&_ti);
215 }
216 break;
217 case slang_oper_call:
218 {
219 int exists;
220
221 if (!_slang_typeof_function (op->a_id, op->children, op->num_children, space, &ti->spec,
222 &exists, atoms))
223 return 0;
224 if (!exists)
225 {
226 /* slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1);
227 if (s != NULL)
228 {
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)
232 return 0;
233 if (!slang_struct_construct (ti->spec._struct))
234 {
235 slang_alloc_free (ti->spec._struct);
236 ti->spec._struct = NULL;
237 return 0;
238 }
239 if (!slang_struct_copy (ti->spec._struct, s))
240 return 0;
241 }
242 else
243 */ {
244 const char *name;
245 slang_type_specifier_type type;
246
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)
250 return 0;
251 ti->spec.type = type;
252 }
253 }
254 }
255 break;
256 case slang_oper_field:
257 {
258 slang_assembly_typeinfo _ti;
259
260 if (!slang_assembly_typeinfo_construct (&_ti))
261 return 0;
262 if (!_slang_typeof_operation (op->children, space, &_ti, atoms))
263 {
264 slang_assembly_typeinfo_destruct (&_ti);
265 return 0;
266 }
267 if (_ti.spec.type == slang_spec_struct)
268 {
269 slang_variable *field;
270
271 field = _slang_locate_variable (_ti.spec._struct->fields, op->a_id, 0);
272 if (field == NULL)
273 {
274 slang_assembly_typeinfo_destruct (&_ti);
275 return 0;
276 }
277 if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier))
278 {
279 slang_assembly_typeinfo_destruct (&_ti);
280 return 0;
281 }
282 ti->can_be_referenced = _ti.can_be_referenced;
283 }
284 else
285 {
286 unsigned int rows;
287 const char *swizzle;
288 slang_type_specifier_type base;
289
290 /* determine the swizzle of the field expression */
291 if (!_slang_type_is_vector (_ti.spec.type))
292 {
293 slang_assembly_typeinfo_destruct (&_ti);
294 return 0;
295 }
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))
299 {
300 slang_assembly_typeinfo_destruct (&_ti);
301 return 0;
302 }
303 ti->is_swizzled = 1;
304 ti->can_be_referenced = _ti.can_be_referenced && _slang_is_swizzle_mask (&ti->swz,
305 rows);
306 if (_ti.is_swizzled)
307 {
308 slang_swizzle swz;
309
310 /* swizzle the swizzle */
311 _slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz);
312 ti->swz = swz;
313 }
314 base = _slang_type_base (_ti.spec.type);
315 switch (ti->swz.num_components)
316 {
317 case 1:
318 ti->spec.type = base;
319 break;
320 case 2:
321 switch (base)
322 {
323 case slang_spec_float:
324 ti->spec.type = slang_spec_vec2;
325 break;
326 case slang_spec_int:
327 ti->spec.type = slang_spec_ivec2;
328 break;
329 case slang_spec_bool:
330 ti->spec.type = slang_spec_bvec2;
331 break;
332 default:
333 _mesa_problem(NULL, "unexepected base in _slang_typeof_operation");
334 ti->spec.type = slang_spec_void;
335 }
336 break;
337 case 3:
338 switch (base)
339 {
340 case slang_spec_float:
341 ti->spec.type = slang_spec_vec3;
342 break;
343 case slang_spec_int:
344 ti->spec.type = slang_spec_ivec3;
345 break;
346 case slang_spec_bool:
347 ti->spec.type = slang_spec_bvec3;
348 break;
349 default:
350 _mesa_problem(NULL, "unexepected base in _slang_typeof_operation");
351 ti->spec.type = slang_spec_void;
352 }
353 break;
354 case 4:
355 switch (base)
356 {
357 case slang_spec_float:
358 ti->spec.type = slang_spec_vec4;
359 break;
360 case slang_spec_int:
361 ti->spec.type = slang_spec_ivec4;
362 break;
363 case slang_spec_bool:
364 ti->spec.type = slang_spec_bvec4;
365 break;
366 default:
367 _mesa_problem(NULL, "unexepected base in _slang_typeof_operation");
368 ti->spec.type = slang_spec_void;
369 }
370 break;
371 default:
372 break;
373 }
374 }
375 slang_assembly_typeinfo_destruct (&_ti);
376 }
377 break;
378 case slang_oper_postincrement:
379 case slang_oper_postdecrement:
380 if (!_slang_typeof_operation (op->children, space, ti, atoms))
381 return 0;
382 ti->can_be_referenced = 0;
383 ti->is_swizzled = 0;
384 break;
385 default:
386 return 0;
387 }
388 return 1;
389 }
390
391 /* _slang_typeof_function() */
392
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)
395 {
396 slang_function *fun;
397
398 fun = _slang_locate_function (space->funcs, a_name, params, num_params, space, atoms);
399 *exists = fun != NULL;
400 if (fun == NULL)
401 return 1;
402 return slang_type_specifier_copy (spec, &fun->header.type.specifier);
403 }
404
405 /* _slang_type_is_matrix() */
406
407 int _slang_type_is_matrix (slang_type_specifier_type ty)
408 {
409 switch (ty)
410 {
411 case slang_spec_mat2:
412 case slang_spec_mat3:
413 case slang_spec_mat4:
414 return 1;
415 default:
416 return 0;
417 }
418 }
419
420 /* _slang_type_is_vector() */
421
422 int _slang_type_is_vector (slang_type_specifier_type ty)
423 {
424 switch (ty)
425 {
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:
435 return 1;
436 default:
437 return 0;
438 }
439 }
440
441 /* _slang_type_base_of_vector() */
442
443 slang_type_specifier_type _slang_type_base (slang_type_specifier_type ty)
444 {
445 switch (ty)
446 {
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;
452 case slang_spec_int:
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;
468 default:
469 return slang_spec_void;
470 }
471 }
472
473 /* _slang_type_dim */
474
475 unsigned int _slang_type_dim (slang_type_specifier_type ty)
476 {
477 switch (ty)
478 {
479 case slang_spec_float:
480 case slang_spec_int:
481 case slang_spec_bool:
482 return 1;
483 case slang_spec_vec2:
484 case slang_spec_ivec2:
485 case slang_spec_bvec2:
486 case slang_spec_mat2:
487 return 2;
488 case slang_spec_vec3:
489 case slang_spec_ivec3:
490 case slang_spec_bvec3:
491 case slang_spec_mat3:
492 return 3;
493 case slang_spec_vec4:
494 case slang_spec_ivec4:
495 case slang_spec_bvec4:
496 case slang_spec_mat4:
497 return 4;
498 default:
499 return 0;
500 }
501 }
502