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