intermediate code generator (not finished);
[mesa.git] / src / mesa / shader / slang / slang_assemble_constructor.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_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 goto end2;
163
164 slang_storage_aggregate_construct (&flat_agg);
165 if (!(result = _slang_flatten_aggregate (&flat_agg, &agg)))
166 goto end;
167
168 if (!(result = _slang_assemble_operation (file, op, 0, flow, space, info, &stk)))
169 goto end;
170
171 for (i = 0; i < flat_agg.count; i++)
172 {
173 const slang_storage_array *arr1 = flat_agg.arrays + i;
174 const slang_storage_array *arr2 = flat->arrays + *index;
175
176 if (arr1->type != arr2->type)
177 {
178 /* TODO: convert (generic) from arr1 to arr2 */
179 }
180 (*index)++;
181 /* TODO: watch the index, if it reaches the size, pop off the stack subsequent values */
182 }
183
184 result = 1;
185 end:
186 slang_storage_aggregate_destruct (&flat_agg);
187 end2:
188 slang_storage_aggregate_destruct (&agg);
189 end1:
190 slang_assembly_typeinfo_destruct (&ti);
191 return result;
192 }
193 /* XXX: general swizzle! */
194 int _slang_assemble_constructor (slang_assembly_file *file, slang_operation *op,
195 slang_assembly_flow_control *flow, slang_assembly_name_space *space,
196 slang_assembly_local_info *info)
197 {
198 slang_assembly_typeinfo ti;
199 int result;
200 slang_storage_aggregate agg, flat;
201 unsigned int size, index, i;
202
203 slang_assembly_typeinfo_construct (&ti);
204 if (!(result = _slang_typeof_operation (op, space, &ti)))
205 goto end1;
206
207 slang_storage_aggregate_construct (&agg);
208 if (!(result = _slang_aggregate_variable (&agg, &ti.spec, NULL, space->funcs, space->structs)))
209 goto end2;
210
211 size = _slang_sizeof_aggregate (&agg);
212
213 slang_storage_aggregate_construct (&flat);
214 if (!(result = _slang_flatten_aggregate (&flat, &agg)))
215 goto end;
216
217 index = 0;
218 for (i = 0; i < op->num_children; i++)
219 {
220 if (!(result = constructor_aggregate (file, &flat, &index, op->children + i, size, flow,
221 space, info)))
222 goto end;
223 /* TODO: watch the index, if it reaches the size, raise an error */
224 }
225
226 result = 1;
227 end:
228 slang_storage_aggregate_destruct (&flat);
229 end2:
230 slang_storage_aggregate_destruct (&agg);
231 end1:
232 slang_assembly_typeinfo_destruct (&ti);
233 return result;
234 }
235
236 /* _slang_assemble_constructor_from_swizzle() */
237 /* XXX: wrong */
238 int _slang_assemble_constructor_from_swizzle (slang_assembly_file *file, const slang_swizzle *swz,
239 slang_type_specifier *spec, slang_type_specifier *master_spec, slang_assembly_local_info *info)
240 {
241 unsigned int master_rows, i;
242 switch (master_spec->type)
243 {
244 case slang_spec_bool:
245 case slang_spec_int:
246 case slang_spec_float:
247 master_rows = 1;
248 break;
249 case slang_spec_bvec2:
250 case slang_spec_ivec2:
251 case slang_spec_vec2:
252 master_rows = 2;
253 break;
254 case slang_spec_bvec3:
255 case slang_spec_ivec3:
256 case slang_spec_vec3:
257 master_rows = 3;
258 break;
259 case slang_spec_bvec4:
260 case slang_spec_ivec4:
261 case slang_spec_vec4:
262 master_rows = 4;
263 break;
264 }
265 for (i = 0; i < master_rows; i++)
266 {
267 switch (master_spec->type)
268 {
269 case slang_spec_bool:
270 case slang_spec_bvec2:
271 case slang_spec_bvec3:
272 case slang_spec_bvec4:
273 if (!slang_assembly_file_push_label2 (file, slang_asm_bool_copy, (master_rows - i) * 4,
274 i * 4))
275 return 0;
276 break;
277 case slang_spec_int:
278 case slang_spec_ivec2:
279 case slang_spec_ivec3:
280 case slang_spec_ivec4:
281 if (!slang_assembly_file_push_label2 (file, slang_asm_int_copy, (master_rows - i) * 4,
282 i * 4))
283 return 0;
284 break;
285 case slang_spec_float:
286 case slang_spec_vec2:
287 case slang_spec_vec3:
288 case slang_spec_vec4:
289 if (!slang_assembly_file_push_label2 (file, slang_asm_float_copy,
290 (master_rows - i) * 4, i * 4))
291 return 0;
292 break;
293 }
294 }
295 if (!slang_assembly_file_push_label (file, slang_asm_local_free, 4))
296 return 0;
297 for (i = swz->num_components; i > 0; i--)
298 {
299 unsigned int n = i - 1;
300 if (!slang_assembly_file_push_label2 (file, slang_asm_local_addr, info->swizzle_tmp, 16))
301 return 0;
302 if (!slang_assembly_file_push_label (file, slang_asm_addr_push, swz->swizzle[n] * 4))
303 return 0;
304 if (!slang_assembly_file_push (file, slang_asm_addr_add))
305 return 0;
306 switch (master_spec->type)
307 {
308 case slang_spec_bool:
309 case slang_spec_bvec2:
310 case slang_spec_bvec3:
311 case slang_spec_bvec4:
312 if (!slang_assembly_file_push (file, slang_asm_bool_deref))
313 return 0;
314 break;
315 case slang_spec_int:
316 case slang_spec_ivec2:
317 case slang_spec_ivec3:
318 case slang_spec_ivec4:
319 if (!slang_assembly_file_push (file, slang_asm_int_deref))
320 return 0;
321 break;
322 case slang_spec_float:
323 case slang_spec_vec2:
324 case slang_spec_vec3:
325 case slang_spec_vec4:
326 if (!slang_assembly_file_push (file, slang_asm_float_deref))
327 return 0;
328 break;
329 }
330 }
331 return 1;
332 }
333