More GLSL code.
[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 GLboolean slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti)
38 {
39 if (!slang_type_specifier_construct (&ti->spec))
40 return GL_FALSE;
41 ti->array_size = NULL;
42 return GL_TRUE;
43 }
44
45 GLvoid 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 GLboolean typeof_existing_function (const char *name, slang_operation *params,
54 GLuint num_params, slang_assembly_name_space *space, slang_type_specifier *spec,
55 slang_atom_pool *atoms)
56 {
57 slang_atom atom;
58 GLboolean 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 GL_FALSE;
63 return exists;
64 }
65
66 GLboolean _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 = GL_FALSE;
70 ti->is_swizzled = GL_FALSE;
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, GL_TRUE);
124 if (var == NULL)
125 return GL_FALSE;
126 if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier))
127 return GL_FALSE;
128 ti->can_be_referenced = GL_TRUE;
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 GL_FALSE;
136 ti->can_be_referenced = GL_FALSE;
137 ti->is_swizzled = GL_FALSE;
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 GL_FALSE;
149 ti->can_be_referenced = GL_FALSE;
150 ti->is_swizzled = GL_FALSE;
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 GL_FALSE;
160 break;
161 case slang_oper_subtract:
162 if (!typeof_existing_function ("-", op->children, 2, space, &ti->spec, atoms))
163 return GL_FALSE;
164 break;
165 case slang_oper_multiply:
166 if (!typeof_existing_function ("*", op->children, 2, space, &ti->spec, atoms))
167 return GL_FALSE;
168 break;
169 case slang_oper_divide:
170 if (!typeof_existing_function ("/", op->children, 2, space, &ti->spec, atoms))
171 return GL_FALSE;
172 break;
173 /*case slang_oper_modulus:*/
174 case slang_oper_plus:
175 if (!_slang_typeof_operation (op->children, space, ti, atoms))
176 return GL_FALSE;
177 ti->can_be_referenced = GL_FALSE;
178 ti->is_swizzled = GL_FALSE;
179 break;
180 case slang_oper_minus:
181 if (!typeof_existing_function ("-", op->children, 1, space, &ti->spec, atoms))
182 return GL_FALSE;
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 GL_FALSE;
191 if (!_slang_typeof_operation (op->children, space, &_ti, atoms))
192 {
193 slang_assembly_typeinfo_destruct (&_ti);
194 return GL_FALSE;
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 GL_FALSE;
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 GL_FALSE;
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 GLboolean exists;
220
221 if (!_slang_typeof_function (op->a_id, op->children, op->num_children, space, &ti->spec,
222 &exists, atoms))
223 return GL_FALSE;
224 if (!exists)
225 {
226 slang_struct *s = slang_struct_scope_find (space->structs, op->a_id, GL_TRUE);
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 GL_FALSE;
233 if (!slang_struct_construct (ti->spec._struct))
234 {
235 slang_alloc_free (ti->spec._struct);
236 ti->spec._struct = NULL;
237 return GL_FALSE;
238 }
239 if (!slang_struct_copy (ti->spec._struct, s))
240 return GL_FALSE;
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 GL_FALSE;
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 GL_FALSE;
262 if (!_slang_typeof_operation (op->children, space, &_ti, atoms))
263 {
264 slang_assembly_typeinfo_destruct (&_ti);
265 return GL_FALSE;
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, GL_FALSE);
272 if (field == NULL)
273 {
274 slang_assembly_typeinfo_destruct (&_ti);
275 return GL_FALSE;
276 }
277 if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier))
278 {
279 slang_assembly_typeinfo_destruct (&_ti);
280 return GL_FALSE;
281 }
282 ti->can_be_referenced = _ti.can_be_referenced;
283 }
284 else
285 {
286 GLuint 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 GL_FALSE;
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 GL_FALSE;
302 }
303 ti->is_swizzled = GL_TRUE;
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 break;
334 }
335 break;
336 case 3:
337 switch (base)
338 {
339 case slang_spec_float:
340 ti->spec.type = slang_spec_vec3;
341 break;
342 case slang_spec_int:
343 ti->spec.type = slang_spec_ivec3;
344 break;
345 case slang_spec_bool:
346 ti->spec.type = slang_spec_bvec3;
347 break;
348 default:
349 break;
350 }
351 break;
352 case 4:
353 switch (base)
354 {
355 case slang_spec_float:
356 ti->spec.type = slang_spec_vec4;
357 break;
358 case slang_spec_int:
359 ti->spec.type = slang_spec_ivec4;
360 break;
361 case slang_spec_bool:
362 ti->spec.type = slang_spec_bvec4;
363 break;
364 default:
365 break;
366 }
367 break;
368 default:
369 break;
370 }
371 }
372 slang_assembly_typeinfo_destruct (&_ti);
373 }
374 break;
375 case slang_oper_postincrement:
376 case slang_oper_postdecrement:
377 if (!_slang_typeof_operation (op->children, space, ti, atoms))
378 return GL_FALSE;
379 ti->can_be_referenced = GL_FALSE;
380 ti->is_swizzled = GL_FALSE;
381 break;
382 default:
383 return GL_FALSE;
384 }
385
386 return GL_TRUE;
387 }
388
389 /* _slang_typeof_function() */
390
391 GLboolean _slang_typeof_function (slang_atom a_name, slang_operation *params, GLuint num_params,
392 slang_assembly_name_space *space, slang_type_specifier *spec, GLboolean *exists,
393 slang_atom_pool *atoms)
394 {
395 slang_function *fun;
396
397 fun = _slang_locate_function (space->funcs, a_name, params, num_params, space, atoms);
398 *exists = fun != NULL;
399 if (fun == NULL)
400 return GL_TRUE;
401 return slang_type_specifier_copy (spec, &fun->header.type.specifier);
402 }
403
404 /* _slang_type_is_matrix() */
405
406 GLboolean _slang_type_is_matrix (slang_type_specifier_type ty)
407 {
408 switch (ty)
409 {
410 case slang_spec_mat2:
411 case slang_spec_mat3:
412 case slang_spec_mat4:
413 return GL_TRUE;
414 default:
415 return GL_FALSE;
416 }
417 }
418
419 /* _slang_type_is_vector() */
420
421 GLboolean _slang_type_is_vector (slang_type_specifier_type ty)
422 {
423 switch (ty)
424 {
425 case slang_spec_vec2:
426 case slang_spec_vec3:
427 case slang_spec_vec4:
428 case slang_spec_ivec2:
429 case slang_spec_ivec3:
430 case slang_spec_ivec4:
431 case slang_spec_bvec2:
432 case slang_spec_bvec3:
433 case slang_spec_bvec4:
434 return GL_TRUE;
435 default:
436 return GL_FALSE;
437 }
438 }
439
440 /* _slang_type_base_of_vector() */
441
442 slang_type_specifier_type _slang_type_base (slang_type_specifier_type ty)
443 {
444 switch (ty)
445 {
446 case slang_spec_float:
447 case slang_spec_vec2:
448 case slang_spec_vec3:
449 case slang_spec_vec4:
450 return slang_spec_float;
451 case slang_spec_int:
452 case slang_spec_ivec2:
453 case slang_spec_ivec3:
454 case slang_spec_ivec4:
455 return slang_spec_int;
456 case slang_spec_bool:
457 case slang_spec_bvec2:
458 case slang_spec_bvec3:
459 case slang_spec_bvec4:
460 return slang_spec_bool;
461 case slang_spec_mat2:
462 return slang_spec_vec2;
463 case slang_spec_mat3:
464 return slang_spec_vec3;
465 case slang_spec_mat4:
466 return slang_spec_vec4;
467 default:
468 return slang_spec_void;
469 }
470 }
471
472 /* _slang_type_dim */
473
474 GLuint _slang_type_dim (slang_type_specifier_type ty)
475 {
476 switch (ty)
477 {
478 case slang_spec_float:
479 case slang_spec_int:
480 case slang_spec_bool:
481 return 1;
482 case slang_spec_vec2:
483 case slang_spec_ivec2:
484 case slang_spec_bvec2:
485 case slang_spec_mat2:
486 return 2;
487 case slang_spec_vec3:
488 case slang_spec_ivec3:
489 case slang_spec_bvec3:
490 case slang_spec_mat3:
491 return 3;
492 case slang_spec_vec4:
493 case slang_spec_ivec4:
494 case slang_spec_bvec4:
495 case slang_spec_mat4:
496 return 4;
497 default:
498 return 0;
499 }
500 }
501