silence gcc warnings
[mesa.git] / src / mesa / shader / slang / slang_assemble_typeinfo.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 2005 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 void slang_assembly_typeinfo_construct (slang_assembly_typeinfo *ti)
38 {
39 slang_type_specifier_construct (&ti->spec);
40 }
41
42 void slang_assembly_typeinfo_destruct (slang_assembly_typeinfo *ti)
43 {
44 slang_type_specifier_destruct (&ti->spec);
45 }
46
47 /* _slang_typeof_operation() */
48
49 int _slang_typeof_operation (slang_operation *op, slang_assembly_name_space *space,
50 slang_assembly_typeinfo *ti)
51 {
52 ti->can_be_referenced = 0;
53 ti->is_swizzled = 0;
54
55 switch (op->type)
56 {
57 case slang_oper_block_no_new_scope:
58 case slang_oper_block_new_scope:
59 case slang_oper_variable_decl:
60 case slang_oper_asm:
61 case slang_oper_break:
62 case slang_oper_continue:
63 case slang_oper_discard:
64 case slang_oper_return:
65 case slang_oper_if:
66 case slang_oper_while:
67 case slang_oper_do:
68 case slang_oper_for:
69 case slang_oper_void:
70 ti->spec.type = slang_spec_void;
71 break;
72 case slang_oper_expression:
73 case slang_oper_assign:
74 case slang_oper_addassign:
75 case slang_oper_subassign:
76 case slang_oper_mulassign:
77 case slang_oper_divassign:
78 case slang_oper_preincrement:
79 case slang_oper_predecrement:
80 if (!_slang_typeof_operation (op->children, space, ti))
81 return 0;
82 break;
83 case slang_oper_literal_bool:
84 case slang_oper_logicalor:
85 case slang_oper_logicalxor:
86 case slang_oper_logicaland:
87 case slang_oper_equal:
88 case slang_oper_notequal:
89 case slang_oper_less:
90 case slang_oper_greater:
91 case slang_oper_lessequal:
92 case slang_oper_greaterequal:
93 case slang_oper_not:
94 ti->spec.type = slang_spec_bool;
95 break;
96 case slang_oper_literal_int:
97 ti->spec.type = slang_spec_int;
98 break;
99 case slang_oper_literal_float:
100 ti->spec.type = slang_spec_float;
101 break;
102 case slang_oper_identifier:
103 {
104 slang_variable *var;
105
106 var = _slang_locate_variable (op->locals, op->identifier, 1);
107 if (var == NULL)
108 return 0;
109 if (!slang_type_specifier_copy (&ti->spec, &var->type.specifier))
110 return 0;
111 ti->can_be_referenced = 1;
112 }
113 break;
114 case slang_oper_sequence:
115 /* TODO: check [0] and [1] if they match */
116 if (!_slang_typeof_operation (op->children + 1, space, ti))
117 return 0;
118 ti->can_be_referenced = 0;
119 ti->is_swizzled = 0;
120 break;
121 /*case slang_oper_modassign:*/
122 /*case slang_oper_lshassign:*/
123 /*case slang_oper_rshassign:*/
124 /*case slang_oper_orassign:*/
125 /*case slang_oper_xorassign:*/
126 /*case slang_oper_andassign:*/
127 case slang_oper_select:
128 /* TODO: check [1] and [2] if they match */
129 if (!_slang_typeof_operation (op->children + 1, space, ti))
130 return 0;
131 ti->can_be_referenced = 0;
132 ti->is_swizzled = 0;
133 break;
134 /*case slang_oper_bitor:*/
135 /*case slang_oper_bitxor:*/
136 /*case slang_oper_bitand:*/
137 /*case slang_oper_lshift:*/
138 /*case slang_oper_rshift:*/
139 case slang_oper_add:
140 {
141 int exists;
142 if (!_slang_typeof_function ("+", op->children, 2, space, &ti->spec, &exists))
143 return 0;
144 if (!exists)
145 return 0;
146 }
147 break;
148 case slang_oper_subtract:
149 {
150 int exists;
151 if (!_slang_typeof_function ("-", op->children, 2, space, &ti->spec, &exists))
152 return 0;
153 if (!exists)
154 return 0;
155 }
156 break;
157 case slang_oper_multiply:
158 {
159 int exists;
160 if (!_slang_typeof_function ("*", op->children, 2, space, &ti->spec, &exists))
161 return 0;
162 if (!exists)
163 return 0;
164 }
165 break;
166 case slang_oper_divide:
167 {
168 int exists;
169 if (!_slang_typeof_function ("/", op->children, 2, space, &ti->spec, &exists))
170 return 0;
171 if (!exists)
172 return 0;
173 }
174 break;
175 /*case slang_oper_modulus:*/
176 case slang_oper_plus:
177 {
178 int exists;
179 if (!_slang_typeof_function ("+", op->children, 1, space, &ti->spec, &exists))
180 return 0;
181 if (!exists)
182 return 0;
183 }
184 break;
185 case slang_oper_minus:
186 {
187 int exists;
188 if (!_slang_typeof_function ("-", op->children, 1, space, &ti->spec, &exists))
189 return 0;
190 if (!exists)
191 return 0;
192 }
193 break;
194 /*case slang_oper_complement:*/
195 case slang_oper_subscript:
196 {
197 slang_assembly_typeinfo _ti;
198 slang_assembly_typeinfo_construct (&_ti);
199 if (!_slang_typeof_operation (op->children, space, &_ti))
200 {
201 slang_assembly_typeinfo_destruct (&_ti);
202 return 0;
203 }
204 ti->can_be_referenced = _ti.can_be_referenced;
205 switch (_ti.spec.type)
206 {
207 case slang_spec_bvec2:
208 case slang_spec_bvec3:
209 case slang_spec_bvec4:
210 ti->spec.type = slang_spec_bool;
211 break;
212 case slang_spec_ivec2:
213 case slang_spec_ivec3:
214 case slang_spec_ivec4:
215 ti->spec.type = slang_spec_int;
216 break;
217 case slang_spec_vec2:
218 case slang_spec_vec3:
219 case slang_spec_vec4:
220 ti->spec.type = slang_spec_float;
221 break;
222 case slang_spec_mat2:
223 ti->spec.type = slang_spec_vec2;
224 break;
225 case slang_spec_mat3:
226 ti->spec.type = slang_spec_vec3;
227 break;
228 case slang_spec_mat4:
229 ti->spec.type = slang_spec_vec4;
230 break;
231 case slang_spec_array:
232 if (!slang_type_specifier_copy (&ti->spec, _ti.spec._array))
233 {
234 slang_assembly_typeinfo_destruct (&_ti);
235 return 0;
236 }
237 break;
238 default:
239 slang_assembly_typeinfo_destruct (&_ti);
240 return 0;
241 }
242 slang_assembly_typeinfo_destruct (&_ti);
243 }
244 break;
245 case slang_oper_call:
246 {
247 int exists;
248 if (!_slang_typeof_function (op->identifier, op->children, op->num_children, space,
249 &ti->spec, &exists))
250 return 0;
251 if (!exists)
252 {
253 slang_struct *s = slang_struct_scope_find (space->structs, op->identifier, 1);
254 if (s != NULL)
255 {
256 ti->spec.type = slang_spec_struct;
257 ti->spec._struct = (slang_struct *) slang_alloc_malloc (sizeof (slang_struct));
258 if (ti->spec._struct == NULL)
259 return 0;
260 if (!slang_struct_construct_a (ti->spec._struct))
261 {
262 slang_alloc_free (ti->spec._struct);
263 ti->spec._struct = NULL;
264 return 0;
265 }
266 if (!slang_struct_copy (ti->spec._struct, s))
267 return 0;
268 }
269 else
270 {
271 slang_type_specifier_type type = slang_type_specifier_type_from_string (
272 op->identifier);
273 if (type == slang_spec_void)
274 return 0;
275 ti->spec.type = type;
276 }
277 }
278 }
279 break;
280 case slang_oper_field:
281 {
282 slang_assembly_typeinfo _ti;
283 slang_assembly_typeinfo_construct (&_ti);
284 if (!_slang_typeof_operation (op->children, space, &_ti))
285 {
286 slang_assembly_typeinfo_destruct (&_ti);
287 return 0;
288 }
289 if (_ti.spec.type == slang_spec_struct)
290 {
291 slang_variable *field = _slang_locate_variable (_ti.spec._struct->fields,
292 op->identifier, 0);
293 if (field == NULL)
294 {
295 slang_assembly_typeinfo_destruct (&_ti);
296 return 0;
297 }
298 if (!slang_type_specifier_copy (&ti->spec, &field->type.specifier))
299 {
300 slang_assembly_typeinfo_destruct (&_ti);
301 return 0;
302 }
303 }
304 else
305 {
306 unsigned int rows;
307 switch (_ti.spec.type)
308 {
309 case slang_spec_vec2:
310 case slang_spec_ivec2:
311 case slang_spec_bvec2:
312 rows = 2;
313 break;
314 case slang_spec_vec3:
315 case slang_spec_ivec3:
316 case slang_spec_bvec3:
317 rows = 3;
318 break;
319 case slang_spec_vec4:
320 case slang_spec_ivec4:
321 case slang_spec_bvec4:
322 rows = 4;
323 break;
324 default:
325 slang_assembly_typeinfo_destruct (&_ti);
326 return 0;
327 }
328 if (!_slang_is_swizzle (op->identifier, rows, &ti->swz))
329 return 0;
330 ti->is_swizzled = 1;
331 ti->can_be_referenced = _ti.can_be_referenced && _slang_is_swizzle_mask (&ti->swz,
332 rows);
333 if (_ti.is_swizzled)
334 {
335 slang_swizzle swz;
336 _slang_multiply_swizzles (&swz, &_ti.swz, &ti->swz);
337 ti->swz = swz;
338 }
339 switch (_ti.spec.type)
340 {
341 case slang_spec_vec2:
342 case slang_spec_vec3:
343 case slang_spec_vec4:
344 switch (ti->swz.num_components)
345 {
346 case 1:
347 ti->spec.type = slang_spec_float;
348 break;
349 case 2:
350 ti->spec.type = slang_spec_vec2;
351 break;
352 case 3:
353 ti->spec.type = slang_spec_vec3;
354 break;
355 case 4:
356 ti->spec.type = slang_spec_vec4;
357 break;
358 }
359 break;
360 case slang_spec_ivec2:
361 case slang_spec_ivec3:
362 case slang_spec_ivec4:
363 switch (ti->swz.num_components)
364 {
365 case 1:
366 ti->spec.type = slang_spec_int;
367 break;
368 case 2:
369 ti->spec.type = slang_spec_ivec2;
370 break;
371 case 3:
372 ti->spec.type = slang_spec_ivec3;
373 break;
374 case 4:
375 ti->spec.type = slang_spec_ivec4;
376 break;
377 }
378 break;
379 case slang_spec_bvec2:
380 case slang_spec_bvec3:
381 case slang_spec_bvec4:
382 switch (ti->swz.num_components)
383 {
384 case 1:
385 ti->spec.type = slang_spec_bool;
386 break;
387 case 2:
388 ti->spec.type = slang_spec_bvec2;
389 break;
390 case 3:
391 ti->spec.type = slang_spec_bvec3;
392 break;
393 case 4:
394 ti->spec.type = slang_spec_bvec4;
395 break;
396 }
397 break;
398 default:
399 break;
400 }
401 }
402 slang_assembly_typeinfo_destruct (&_ti);
403 return 1;
404 }
405 break;
406 case slang_oper_postincrement:
407 case slang_oper_postdecrement:
408 if (!_slang_typeof_operation (op->children, space, ti))
409 return 0;
410 ti->can_be_referenced = 0;
411 ti->is_swizzled = 0;
412 break;
413 default:
414 return 0;
415 }
416 return 1;
417 }
418
419 /* _slang_typeof_function() */
420
421 int _slang_typeof_function (const char *name, slang_operation *params, unsigned int num_params,
422 slang_assembly_name_space *space, slang_type_specifier *spec, int *exists)
423 {
424 slang_function *fun = _slang_locate_function (name, params, num_params, space);
425 *exists = fun != NULL;
426 if (fun == NULL)
427 return 1;
428 return slang_type_specifier_copy (spec, &fun->header.type.specifier);
429 }
430