Split slang_compile.c into several smaller files - it was just too big.
[mesa.git] / src / mesa / shader / slang / slang_assemble_constructor.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_constructor.c
27 * slang constructor and vector swizzle assembler
28 * \author Michal Krol
29 */
30
31 #include "imports.h"
32 #include "slang_utility.h"
33 #include "slang_assemble_constructor.h"
34 #include "slang_assemble_typeinfo.h"
35 #include "slang_storage.h"
36
37 /* _slang_is_swizzle() */
38
39 int _slang_is_swizzle (const char *field, unsigned int rows, slang_swizzle *swz)
40 {
41 unsigned int i;
42 int xyzw = 0, rgba = 0, stpq = 0;
43
44 /* the swizzle can be at most 4-component long */
45 swz->num_components = slang_string_length (field);
46 if (swz->num_components > 4)
47 return 0;
48
49 for (i = 0; i < swz->num_components; i++)
50 {
51 /* mark which swizzle group is used */
52 switch (field[i])
53 {
54 case 'x':
55 case 'y':
56 case 'z':
57 case 'w':
58 xyzw = 1;
59 break;
60 case 'r':
61 case 'g':
62 case 'b':
63 case 'a':
64 rgba = 1;
65 break;
66 case 's':
67 case 't':
68 case 'p':
69 case 'q':
70 stpq = 1;
71 break;
72 default:
73 return 0;
74 }
75
76 /* collect swizzle component */
77 switch (field[i])
78 {
79 case 'x':
80 case 'r':
81 case 's':
82 swz->swizzle[i] = 0;
83 break;
84 case 'y':
85 case 'g':
86 case 't':
87 if (rows < 2)
88 return 0;
89 swz->swizzle[i] = 1;
90 break;
91 case 'z':
92 case 'b':
93 case 'p':
94 if (rows < 3)
95 return 0;
96 swz->swizzle[i] = 2;
97 break;
98 case 'w':
99 case 'a':
100 case 'q':
101 if (rows < 4)
102 return 0;
103 swz->swizzle[i] = 3;
104 break;
105 }
106 }
107
108 /* only one swizzle group can be used */
109 if ((xyzw && rgba) || (xyzw && stpq) || (rgba && stpq))
110 return 0;
111
112 return 1;
113 }
114
115 /* _slang_is_swizzle_mask() */
116
117 int _slang_is_swizzle_mask (const slang_swizzle *swz, unsigned int rows)
118 {
119 unsigned int c, i;
120
121 if (swz->num_components > rows)
122 return 0;
123 c = swz->swizzle[0];
124 for (i = 1; i < swz->num_components; i++)
125 {
126 if (swz->swizzle[i] <= c)
127 return 0;
128 c = swz->swizzle[i];
129 }
130 return 1;
131 }
132
133 /* _slang_multiply_swizzles() */
134
135 void _slang_multiply_swizzles (slang_swizzle *dst, const slang_swizzle *left,
136 const slang_swizzle *right)
137 {
138 unsigned int i;
139 dst->num_components = right->num_components;
140 for (i = 0; i < right->num_components; i++)
141 dst->swizzle[i] = left->swizzle[right->swizzle[i]];
142 }
143
144 /* _slang_assemble_constructor() */
145
146 static int constructor_aggregate (slang_assembly_file *file, const slang_storage_aggregate *flat,
147 unsigned int *index, slang_operation *op, unsigned int size, slang_assembly_flow_control *flow,
148 slang_assembly_name_space *space, slang_assembly_local_info *info)
149 {
150 slang_assembly_typeinfo ti;
151 int result;
152 slang_storage_aggregate agg, flat_agg;
153 slang_assembly_stack_info stk;
154 unsigned int i;
155
156 slang_assembly_typeinfo_construct (&ti);
157 if (!(result = _slang_typeof_operation (op, space, &ti)))
158 goto end1;
159
160 slang_storage_aggregate_construct (&agg);
161 if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs,
162 space->vars)))
163 goto end2;
164
165 slang_storage_aggregate_construct (&flat_agg);
166 if (!(result = _slang_flatten_aggregate (&flat_agg, &agg)))
167 goto end;
168
169 if (!(result = _slang_assemble_operation (file, op, 0, flow, space, info, &stk)))
170 goto end;
171
172 for (i = 0; i < flat_agg.count; i++)
173 {
174 const slang_storage_array *arr1 = flat_agg.arrays + i;
175 const slang_storage_array *arr2 = flat->arrays + *index;
176
177 if (arr1->type != arr2->type)
178 {
179 /* TODO: convert (generic) from arr1 to arr2 */
180 }
181 (*index)++;
182 /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
183 }
184
185 result = 1;
186 end:
187 slang_storage_aggregate_destruct (&flat_agg);
188 end2:
189 slang_storage_aggregate_destruct (&agg);
190 end1:
191 slang_assembly_typeinfo_destruct (&ti);
192 return result;
193 }
194 /* XXX: general swizzle! */
195 int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op,
196 slang_assembly_flow_control *flow, slang_assembly_name_space *space,
197 slang_assembly_local_info *info)
198 {
199 slang_assembly_typeinfo ti;
200 int result;
201 slang_storage_aggregate agg, flat;
202 unsigned int size, index, i;
203
204 slang_assembly_typeinfo_construct (&ti);
205 if (!(result = _slang_typeof_operation (op, space, &ti)))
206 goto end1;
207
208 slang_storage_aggregate_construct (&agg);
209 if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs,
210 space->vars)))
211 goto end2;
212
213 size = _slang_sizeof_aggregate (&agg);
214
215 slang_storage_aggregate_construct (&flat);
216 if (!(result = _slang_flatten_aggregate (&flat, &agg)))
217 goto end;
218
219 index = 0;
220 for (i = 0; i < op->num_children; i++)
221 {
222 if (!(result = constructor_aggregate (file, &flat, &index, op->children + i, size, flow,
223 space, info)))
224 goto end;
225 /* TODO: watch the index, if it reaches the size, raise an error */
226 }
227
228 result = 1;
229 end:
230 slang_storage_aggregate_destruct (&flat);
231 end2:
232 slang_storage_aggregate_destruct (&agg);
233 end1:
234 slang_assembly_typeinfo_destruct (&ti);
235 return result;
236 }
237
238 /* _slang_assemble_constructor_from_swizzle() */
239 /* XXX: wrong */
240 int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz,
241 slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info)
242 {
243 unsigned int master_rows, i;
244 switch (master_spec->type)
245 {
246 case slang_spec_bool:
247 case slang_spec_int:
248 case slang_spec_float:
249 master_rows = 1;
250 break;
251 case slang_spec_bvec2:
252 case slang_spec_ivec2:
253 case slang_spec_vec2:
254 master_rows = 2;
255 break;
256 case slang_spec_bvec3:
257 case slang_spec_ivec3:
258 case slang_spec_vec3:
259 master_rows = 3;
260 break;
261 case slang_spec_bvec4:
262 case slang_spec_ivec4:
263 case slang_spec_vec4:
264 master_rows = 4;
265 break;
266 default:
267 break;
268 }
269 for (i = 0; i < master_rows; i++)
270 {
271 switch (master_spec->type)
272 {
273 case slang_spec_bool:
274 case slang_spec_bvec2:
275 case slang_spec_bvec3:
276 case slang_spec_bvec4:
277 if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy, (master_rows - i) * 4,
278 i * 4))
279 return 0;
280 break;
281 case slang_spec_int:
282 case slang_spec_ivec2:
283 case slang_spec_ivec3:
284 case slang_spec_ivec4:
285 if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy, (master_rows - i) * 4,
286 i * 4))
287 return 0;
288 break;
289 case slang_spec_float:
290 case slang_spec_vec2:
291 case slang_spec_vec3:
292 case slang_spec_vec4:
293 if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy,
294 (master_rows - i) * 4, i * 4))
295 return 0;
296 break;
297 default:
298 break;
299 }
300 }
301 if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
302 return 0;
303 for (i = swz->num_components; i > 0; i--)
304 {
305 unsigned int n = i - 1;
306 if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->swizzle_tmp, 16))
307 return 0;
308 if (!slang_assembly_file_push_label (file, slang_asm_addr_push, swz->swizzle[n] * 4))
309 return 0;
310 if (!slang_assembly_file_push (file, slang_asm_addr_add))
311 return 0;
312 switch (master_spec->type)
313 {
314 case slang_spec_bool:
315 case slang_spec_bvec2:
316 case slang_spec_bvec3:
317 case slang_spec_bvec4:
318 if (!slang_assembly_file_push (file, slang_asm_bool_deref))
319 return 0;
320 break;
321 case slang_spec_int:
322 case slang_spec_ivec2:
323 case slang_spec_ivec3:
324 case slang_spec_ivec4:
325 if (!slang_assembly_file_push (file, slang_asm_int_deref))
326 return 0;
327 break;
328 case slang_spec_float:
329 case slang_spec_vec2:
330 case slang_spec_vec3:
331 case slang_spec_vec4:
332 if (!slang_assembly_file_push (file, slang_asm_float_deref))
333 return 0;
334 break;
335 default:
336 break;
337 }
338 }
339 return 1;
340 }
341