mesa: move shader/slang/* sources to main/slang/*
[mesa.git] / src / mesa / slang / slang_compile_operation.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.2
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_compile_operation.c
27 * slang front-end compiler
28 * \author Michal Krol
29 */
30
31 #include "main/imports.h"
32 #include "slang_compile.h"
33 #include "slang_mem.h"
34
35
36 /**
37 * Init a slang_operation object
38 */
39 GLboolean
40 slang_operation_construct(slang_operation * oper)
41 {
42 oper->type = SLANG_OPER_NONE;
43 oper->children = NULL;
44 oper->num_children = 0;
45 oper->literal[0] = 0.0;
46 oper->literal_size = 1;
47 oper->array_constructor = GL_FALSE;
48 oper->a_id = SLANG_ATOM_NULL;
49 oper->a_obj = SLANG_ATOM_NULL;
50 oper->locals = _slang_variable_scope_new(NULL);
51 if (oper->locals == NULL)
52 return GL_FALSE;
53 _slang_variable_scope_ctr(oper->locals);
54 oper->fun = NULL;
55 oper->var = NULL;
56 oper->label = NULL;
57 return GL_TRUE;
58 }
59
60 void
61 slang_operation_destruct(slang_operation * oper)
62 {
63 GLuint i;
64
65 for (i = 0; i < oper->num_children; i++)
66 slang_operation_destruct(oper->children + i);
67 _slang_free(oper->children);
68 slang_variable_scope_destruct(oper->locals);
69 _slang_free(oper->locals);
70 oper->children = NULL;
71 oper->num_children = 0;
72 oper->locals = NULL;
73 }
74
75
76 /**
77 * Recursively traverse 'oper', replacing occurances of 'oldScope' with
78 * 'newScope' in the oper->locals->outer_scope field.
79 */
80 void
81 slang_replace_scope(slang_operation *oper,
82 slang_variable_scope *oldScope,
83 slang_variable_scope *newScope)
84 {
85 GLuint i;
86
87 if (oper->locals != newScope &&
88 oper->locals->outer_scope == oldScope) {
89 /* found. replace old w/ new */
90 oper->locals->outer_scope = newScope;
91 }
92
93 if (oper->type == SLANG_OPER_VARIABLE_DECL) {
94 /* search/replace in the initializer */
95 slang_variable *var;
96 var = _slang_variable_locate(oper->locals, oper->a_id, GL_TRUE);
97 if (var && var->initializer) {
98 slang_replace_scope(var->initializer, oldScope, newScope);
99 }
100 }
101
102 /* search/replace in children */
103 for (i = 0; i < oper->num_children; i++) {
104 slang_replace_scope(&oper->children[i], oldScope, newScope);
105 }
106 }
107
108
109 /**
110 * Recursively copy a slang_operation node.
111 * \param x copy target
112 * \param y copy source
113 * \return GL_TRUE for success, GL_FALSE if failure
114 */
115 GLboolean
116 slang_operation_copy(slang_operation * x, const slang_operation * y)
117 {
118 slang_operation z;
119 GLuint i;
120
121 if (!slang_operation_construct(&z))
122 return GL_FALSE;
123 z.type = y->type;
124 if (y->num_children > 0) {
125 z.children = (slang_operation *)
126 _slang_alloc(y->num_children * sizeof(slang_operation));
127 if (z.children == NULL) {
128 slang_operation_destruct(&z);
129 return GL_FALSE;
130 }
131 }
132 for (z.num_children = 0; z.num_children < y->num_children;
133 z.num_children++) {
134 if (!slang_operation_construct(&z.children[z.num_children])) {
135 slang_operation_destruct(&z);
136 return GL_FALSE;
137 }
138 }
139 for (i = 0; i < z.num_children; i++) {
140 if (!slang_operation_copy(&z.children[i], &y->children[i])) {
141 slang_operation_destruct(&z);
142 return GL_FALSE;
143 }
144 }
145 z.literal[0] = y->literal[0];
146 z.literal[1] = y->literal[1];
147 z.literal[2] = y->literal[2];
148 z.literal[3] = y->literal[3];
149 z.literal_size = y->literal_size;
150 assert(y->literal_size >= 1);
151 assert(y->literal_size <= 4);
152 z.a_id = y->a_id;
153 if (y->locals) {
154 if (!slang_variable_scope_copy(z.locals, y->locals)) {
155 slang_operation_destruct(&z);
156 return GL_FALSE;
157 }
158 }
159
160 /* update scoping for children */
161 for (i = 0; i < y->num_children; i++) {
162 if (y->children[i].locals &&
163 y->children[i].locals->outer_scope == y->locals) {
164 z.children[i].locals->outer_scope = z.locals;
165 }
166 }
167
168 #if 0
169 z.var = y->var;
170 z.fun = y->fun;
171 #endif
172 slang_operation_destruct(x);
173 *x = z;
174
175 /* If this operation declares a new scope, we need to make sure
176 * all children point to it, not the original operation's scope!
177 */
178 if (x->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
179 x->type == SLANG_OPER_WHILE ||
180 x->type == SLANG_OPER_FOR) {
181 slang_replace_scope(x, y->locals, x->locals);
182 }
183
184 return GL_TRUE;
185 }
186
187
188 slang_operation *
189 slang_operation_new(GLuint count)
190 {
191 slang_operation *ops
192 = (slang_operation *) _slang_alloc(count * sizeof(slang_operation));
193 assert(count > 0);
194 if (ops) {
195 GLuint i;
196 for (i = 0; i < count; i++)
197 slang_operation_construct(ops + i);
198 }
199 return ops;
200 }
201
202
203 /**
204 * Delete operation and all children
205 */
206 void
207 slang_operation_delete(slang_operation *oper)
208 {
209 slang_operation_destruct(oper);
210 _slang_free(oper);
211 }
212
213
214 void
215 slang_operation_free_children(slang_operation *oper)
216 {
217 GLuint i;
218 for (i = 0; i < slang_oper_num_children(oper); i++) {
219 slang_operation *child = slang_oper_child(oper, i);
220 slang_operation_destruct(child);
221 }
222 _slang_free(oper->children);
223 oper->children = NULL;
224 oper->num_children = 0;
225 }
226
227
228 slang_operation *
229 slang_operation_grow(GLuint *numChildren, slang_operation **children)
230 {
231 slang_operation *ops;
232
233 ops = (slang_operation *)
234 _slang_realloc(*children,
235 *numChildren * sizeof(slang_operation),
236 (*numChildren + 1) * sizeof(slang_operation));
237 if (ops) {
238 slang_operation *newOp = ops + *numChildren;
239 if (!slang_operation_construct(newOp)) {
240 _slang_free(ops);
241 *children = NULL;
242 return NULL;
243 }
244 *children = ops;
245 (*numChildren)++;
246 return newOp;
247 }
248 return NULL;
249 }
250
251 /**
252 * Insert a new slang_operation into an array.
253 * \param numElements pointer to current array size (in/out)
254 * \param array address of the array (in/out)
255 * \param pos position to insert new element
256 * \return pointer to the new operation/element
257 */
258 slang_operation *
259 slang_operation_insert(GLuint *numElements, slang_operation **array,
260 GLuint pos)
261 {
262 slang_operation *ops;
263
264 assert(pos <= *numElements);
265
266 ops = (slang_operation *)
267 _slang_alloc((*numElements + 1) * sizeof(slang_operation));
268 if (ops) {
269 slang_operation *newOp;
270 newOp = ops + pos;
271 if (pos > 0)
272 memcpy(ops, *array, pos * sizeof(slang_operation));
273 if (pos < *numElements)
274 memcpy(newOp + 1, (*array) + pos,
275 (*numElements - pos) * sizeof(slang_operation));
276
277 if (!slang_operation_construct(newOp)) {
278 _slang_free(ops);
279 *numElements = 0;
280 *array = NULL;
281 return NULL;
282 }
283 if (*array)
284 _slang_free(*array);
285 *array = ops;
286 (*numElements)++;
287 return newOp;
288 }
289 return NULL;
290 }
291
292
293 /**
294 * Add/insert new child into given node at given position.
295 * \return pointer to the new child node
296 */
297 slang_operation *
298 slang_operation_insert_child(slang_operation *oper, GLuint pos)
299 {
300 slang_operation *newOp;
301
302 newOp = slang_operation_insert(&oper->num_children,
303 &oper->children,
304 pos);
305 if (newOp) {
306 newOp->locals->outer_scope = oper->locals;
307 }
308
309 return newOp;
310 }
311
312
313 void
314 _slang_operation_swap(slang_operation *oper0, slang_operation *oper1)
315 {
316 slang_operation tmp = *oper0;
317 *oper0 = *oper1;
318 *oper1 = tmp;
319 }
320
321
322 void
323 slang_operation_add_children(slang_operation *oper, GLuint num_children)
324 {
325 GLuint i;
326 assert(oper->num_children == 0);
327 assert(oper->children == NULL);
328 oper->num_children = num_children;
329 oper->children = slang_operation_new(num_children);
330 for (i = 0; i < num_children; i++) {
331 oper->children[i].locals = _slang_variable_scope_new(oper->locals);
332 }
333 }
334