Merge commit 'origin/gallium-0.1' into gallium-0.2
[mesa.git] / src / mesa / shader / slang / slang_compile_variable.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 2005-2007 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_variable.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 typedef struct
37 {
38 const char *name;
39 slang_type_specifier_type type;
40 } type_specifier_type_name;
41
42 static const type_specifier_type_name type_specifier_type_names[] = {
43 {"void", SLANG_SPEC_VOID},
44 {"bool", SLANG_SPEC_BOOL},
45 {"bvec2", SLANG_SPEC_BVEC2},
46 {"bvec3", SLANG_SPEC_BVEC3},
47 {"bvec4", SLANG_SPEC_BVEC4},
48 {"int", SLANG_SPEC_INT},
49 {"ivec2", SLANG_SPEC_IVEC2},
50 {"ivec3", SLANG_SPEC_IVEC3},
51 {"ivec4", SLANG_SPEC_IVEC4},
52 {"float", SLANG_SPEC_FLOAT},
53 {"vec2", SLANG_SPEC_VEC2},
54 {"vec3", SLANG_SPEC_VEC3},
55 {"vec4", SLANG_SPEC_VEC4},
56 {"mat2", SLANG_SPEC_MAT2},
57 {"mat3", SLANG_SPEC_MAT3},
58 {"mat4", SLANG_SPEC_MAT4},
59 {"mat2x3", SLANG_SPEC_MAT23},
60 {"mat3x2", SLANG_SPEC_MAT32},
61 {"mat2x4", SLANG_SPEC_MAT24},
62 {"mat4x2", SLANG_SPEC_MAT42},
63 {"mat3x4", SLANG_SPEC_MAT34},
64 {"mat4x3", SLANG_SPEC_MAT43},
65 {"sampler1D", SLANG_SPEC_SAMPLER1D},
66 {"sampler2D", SLANG_SPEC_SAMPLER2D},
67 {"sampler3D", SLANG_SPEC_SAMPLER3D},
68 {"samplerCube", SLANG_SPEC_SAMPLERCUBE},
69 {"sampler1DShadow", SLANG_SPEC_SAMPLER1DSHADOW},
70 {"sampler2DShadow", SLANG_SPEC_SAMPLER2DSHADOW},
71 {"sampler2DRect", SLANG_SPEC_SAMPLER2DRECT},
72 {"sampler2DRectShadow", SLANG_SPEC_SAMPLER2DRECTSHADOW},
73 {NULL, SLANG_SPEC_VOID}
74 };
75
76 slang_type_specifier_type
77 slang_type_specifier_type_from_string(const char *name)
78 {
79 const type_specifier_type_name *p = type_specifier_type_names;
80 while (p->name != NULL) {
81 if (slang_string_compare(p->name, name) == 0)
82 break;
83 p++;
84 }
85 return p->type;
86 }
87
88 const char *
89 slang_type_specifier_type_to_string(slang_type_specifier_type type)
90 {
91 const type_specifier_type_name *p = type_specifier_type_names;
92 while (p->name != NULL) {
93 if (p->type == type)
94 break;
95 p++;
96 }
97 return p->name;
98 }
99
100 /* slang_fully_specified_type */
101
102 int
103 slang_fully_specified_type_construct(slang_fully_specified_type * type)
104 {
105 type->qualifier = SLANG_QUAL_NONE;
106 slang_type_specifier_ctr(&type->specifier);
107 return 1;
108 }
109
110 void
111 slang_fully_specified_type_destruct(slang_fully_specified_type * type)
112 {
113 slang_type_specifier_dtr(&type->specifier);
114 }
115
116 int
117 slang_fully_specified_type_copy(slang_fully_specified_type * x,
118 const slang_fully_specified_type * y)
119 {
120 slang_fully_specified_type z;
121
122 if (!slang_fully_specified_type_construct(&z))
123 return 0;
124 z.qualifier = y->qualifier;
125 z.precision = y->precision;
126 z.variant = y->variant;
127 z.centroid = y->centroid;
128 if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
129 slang_fully_specified_type_destruct(&z);
130 return 0;
131 }
132 slang_fully_specified_type_destruct(x);
133 *x = z;
134 return 1;
135 }
136
137
138 static slang_variable *
139 slang_variable_new(void)
140 {
141 slang_variable *v = (slang_variable *) _slang_alloc(sizeof(slang_variable));
142 if (v) {
143 if (!slang_variable_construct(v)) {
144 _slang_free(v);
145 v = NULL;
146 }
147 }
148 return v;
149 }
150
151
152 static void
153 slang_variable_delete(slang_variable * var)
154 {
155 slang_variable_destruct(var);
156 _slang_free(var);
157 }
158
159
160 /*
161 * slang_variable_scope
162 */
163
164 slang_variable_scope *
165 _slang_variable_scope_new(slang_variable_scope *parent)
166 {
167 slang_variable_scope *s;
168 s = (slang_variable_scope *) _slang_alloc(sizeof(slang_variable_scope));
169 if (s)
170 s->outer_scope = parent;
171 return s;
172 }
173
174
175 GLvoid
176 _slang_variable_scope_ctr(slang_variable_scope * self)
177 {
178 self->variables = NULL;
179 self->num_variables = 0;
180 self->outer_scope = NULL;
181 }
182
183 void
184 slang_variable_scope_destruct(slang_variable_scope * scope)
185 {
186 unsigned int i;
187
188 if (!scope)
189 return;
190 for (i = 0; i < scope->num_variables; i++) {
191 if (scope->variables[i])
192 slang_variable_delete(scope->variables[i]);
193 }
194 _slang_free(scope->variables);
195 /* do not free scope->outer_scope */
196 }
197
198 int
199 slang_variable_scope_copy(slang_variable_scope * x,
200 const slang_variable_scope * y)
201 {
202 slang_variable_scope z;
203 unsigned int i;
204
205 _slang_variable_scope_ctr(&z);
206 z.variables = (slang_variable **)
207 _slang_alloc(y->num_variables * sizeof(slang_variable *));
208 if (z.variables == NULL) {
209 slang_variable_scope_destruct(&z);
210 return 0;
211 }
212 for (z.num_variables = 0; z.num_variables < y->num_variables;
213 z.num_variables++) {
214 z.variables[z.num_variables] = slang_variable_new();
215 if (!z.variables[z.num_variables]) {
216 slang_variable_scope_destruct(&z);
217 return 0;
218 }
219 }
220 for (i = 0; i < z.num_variables; i++) {
221 if (!slang_variable_copy(z.variables[i], y->variables[i])) {
222 slang_variable_scope_destruct(&z);
223 return 0;
224 }
225 }
226 z.outer_scope = y->outer_scope;
227 slang_variable_scope_destruct(x);
228 *x = z;
229 return 1;
230 }
231
232
233 /**
234 * Grow the variable list by one.
235 * \return pointer to space for the new variable (will be initialized)
236 */
237 slang_variable *
238 slang_variable_scope_grow(slang_variable_scope *scope)
239 {
240 const int n = scope->num_variables;
241 scope->variables = (slang_variable **)
242 _slang_realloc(scope->variables,
243 n * sizeof(slang_variable *),
244 (n + 1) * sizeof(slang_variable *));
245 if (!scope->variables)
246 return NULL;
247
248 scope->num_variables++;
249
250 scope->variables[n] = slang_variable_new();
251 if (!scope->variables[n])
252 return NULL;
253
254 return scope->variables[n];
255 }
256
257
258
259 /* slang_variable */
260
261 int
262 slang_variable_construct(slang_variable * var)
263 {
264 if (!slang_fully_specified_type_construct(&var->type))
265 return 0;
266 var->a_name = SLANG_ATOM_NULL;
267 var->array_len = 0;
268 var->initializer = NULL;
269 var->address = ~0;
270 var->size = 0;
271 var->isTemp = GL_FALSE;
272 var->store = NULL;
273 var->declared = 0;
274 return 1;
275 }
276
277
278 void
279 slang_variable_destruct(slang_variable * var)
280 {
281 slang_fully_specified_type_destruct(&var->type);
282 if (var->initializer != NULL) {
283 slang_operation_destruct(var->initializer);
284 _slang_free(var->initializer);
285 }
286 #if 0
287 if (var->aux) {
288 _mesa_free(var->aux);
289 }
290 #endif
291 }
292
293
294 int
295 slang_variable_copy(slang_variable * x, const slang_variable * y)
296 {
297 slang_variable z;
298
299 if (!slang_variable_construct(&z))
300 return 0;
301 if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
302 slang_variable_destruct(&z);
303 return 0;
304 }
305 z.a_name = y->a_name;
306 z.array_len = y->array_len;
307 if (y->initializer != NULL) {
308 z.initializer
309 = (slang_operation *) _slang_alloc(sizeof(slang_operation));
310 if (z.initializer == NULL) {
311 slang_variable_destruct(&z);
312 return 0;
313 }
314 if (!slang_operation_construct(z.initializer)) {
315 _slang_free(z.initializer);
316 slang_variable_destruct(&z);
317 return 0;
318 }
319 if (!slang_operation_copy(z.initializer, y->initializer)) {
320 slang_variable_destruct(&z);
321 return 0;
322 }
323 }
324 z.address = y->address;
325 z.size = y->size;
326 slang_variable_destruct(x);
327 *x = z;
328 return 1;
329 }
330
331
332 /**
333 * Search for named variable in given scope.
334 * \param all if true, search parent scopes too.
335 */
336 slang_variable *
337 _slang_locate_variable(const slang_variable_scope * scope,
338 const slang_atom a_name, GLboolean all)
339 {
340 while (scope) {
341 GLuint i;
342 for (i = 0; i < scope->num_variables; i++)
343 if (a_name == scope->variables[i]->a_name)
344 return scope->variables[i];
345 if (all)
346 scope = scope->outer_scope;
347 else
348 scope = NULL;
349 }
350 return NULL;
351 }