Merge branch 'master' of git+ssh://brianp@git.freedesktop.org/git/mesa/mesa into...
[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 "imports.h"
32 #include "slang_compile.h"
33
34 /* slang_type_specifier_type */
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 {"sampler1D", SLANG_SPEC_SAMPLER1D},
60 {"sampler2D", SLANG_SPEC_SAMPLER2D},
61 {"sampler3D", SLANG_SPEC_SAMPLER3D},
62 {"samplerCube", SLANG_SPEC_SAMPLERCUBE},
63 {"sampler1DShadow", SLANG_SPEC_SAMPLER1DSHADOW},
64 {"sampler2DShadow", SLANG_SPEC_SAMPLER2DSHADOW},
65 {NULL, SLANG_SPEC_VOID}
66 };
67
68 slang_type_specifier_type
69 slang_type_specifier_type_from_string(const char *name)
70 {
71 const type_specifier_type_name *p = type_specifier_type_names;
72 while (p->name != NULL) {
73 if (slang_string_compare(p->name, name) == 0)
74 break;
75 p++;
76 }
77 return p->type;
78 }
79
80 const char *
81 slang_type_specifier_type_to_string(slang_type_specifier_type type)
82 {
83 const type_specifier_type_name *p = type_specifier_type_names;
84 while (p->name != NULL) {
85 if (p->type == type)
86 break;
87 p++;
88 }
89 return p->name;
90 }
91
92 /* slang_fully_specified_type */
93
94 int
95 slang_fully_specified_type_construct(slang_fully_specified_type * type)
96 {
97 type->qualifier = SLANG_QUAL_NONE;
98 slang_type_specifier_ctr(&type->specifier);
99 return 1;
100 }
101
102 void
103 slang_fully_specified_type_destruct(slang_fully_specified_type * type)
104 {
105 slang_type_specifier_dtr(&type->specifier);
106 }
107
108 int
109 slang_fully_specified_type_copy(slang_fully_specified_type * x,
110 const slang_fully_specified_type * y)
111 {
112 slang_fully_specified_type z;
113
114 if (!slang_fully_specified_type_construct(&z))
115 return 0;
116 z.qualifier = y->qualifier;
117 if (!slang_type_specifier_copy(&z.specifier, &y->specifier)) {
118 slang_fully_specified_type_destruct(&z);
119 return 0;
120 }
121 slang_fully_specified_type_destruct(x);
122 *x = z;
123 return 1;
124 }
125
126
127 static slang_variable *
128 slang_variable_new(void)
129 {
130 slang_variable *v = (slang_variable *) malloc(sizeof(slang_variable));
131 if (v) {
132 if (!slang_variable_construct(v)) {
133 free(v);
134 v = NULL;
135 }
136 }
137 return v;
138 }
139
140
141 static void
142 slang_variable_delete(slang_variable * var)
143 {
144 slang_variable_destruct(var);
145 free(var);
146 }
147
148
149 /*
150 * slang_variable_scope
151 */
152
153 slang_variable_scope *
154 _slang_variable_scope_new(slang_variable_scope *parent)
155 {
156 slang_variable_scope *s;
157 s = (slang_variable_scope *) _mesa_calloc(sizeof(slang_variable_scope));
158 s->outer_scope = parent;
159 return s;
160 }
161
162
163 GLvoid
164 _slang_variable_scope_ctr(slang_variable_scope * self)
165 {
166 self->variables = NULL;
167 self->num_variables = 0;
168 self->outer_scope = NULL;
169 }
170
171 void
172 slang_variable_scope_destruct(slang_variable_scope * scope)
173 {
174 unsigned int i;
175
176 if (!scope)
177 return;
178 for (i = 0; i < scope->num_variables; i++) {
179 if (scope->variables[i])
180 slang_variable_delete(scope->variables[i]);
181 }
182 slang_alloc_free(scope->variables);
183 /* do not free scope->outer_scope */
184 }
185
186 int
187 slang_variable_scope_copy(slang_variable_scope * x,
188 const slang_variable_scope * y)
189 {
190 slang_variable_scope z;
191 unsigned int i;
192
193 _slang_variable_scope_ctr(&z);
194 z.variables = (slang_variable **)
195 _mesa_calloc(y->num_variables * sizeof(slang_variable *));
196 if (z.variables == NULL) {
197 slang_variable_scope_destruct(&z);
198 return 0;
199 }
200 for (z.num_variables = 0; z.num_variables < y->num_variables;
201 z.num_variables++) {
202 z.variables[z.num_variables] = slang_variable_new();
203 if (!z.variables[z.num_variables]) {
204 slang_variable_scope_destruct(&z);
205 return 0;
206 }
207 }
208 for (i = 0; i < z.num_variables; i++) {
209 if (!slang_variable_copy(z.variables[i], y->variables[i])) {
210 slang_variable_scope_destruct(&z);
211 return 0;
212 }
213 }
214 z.outer_scope = y->outer_scope;
215 slang_variable_scope_destruct(x);
216 *x = z;
217 return 1;
218 }
219
220
221 /**
222 * Grow the variable list by one.
223 * \return pointer to space for the new variable (will be initialized)
224 */
225 slang_variable *
226 slang_variable_scope_grow(slang_variable_scope *scope)
227 {
228 const int n = scope->num_variables;
229 scope->variables = (slang_variable **)
230 slang_alloc_realloc(scope->variables,
231 n * sizeof(slang_variable *),
232 (n + 1) * sizeof(slang_variable *));
233 if (!scope->variables)
234 return NULL;
235
236 scope->num_variables++;
237
238 scope->variables[n] = slang_variable_new();
239 if (!scope->variables[n])
240 return NULL;
241
242 return scope->variables[n];
243 }
244
245
246
247 /* slang_variable */
248
249 int
250 slang_variable_construct(slang_variable * var)
251 {
252 if (!slang_fully_specified_type_construct(&var->type))
253 return 0;
254 var->a_name = SLANG_ATOM_NULL;
255 var->array_len = 0;
256 var->initializer = NULL;
257 var->address = ~0;
258 var->size = 0;
259 var->isTemp = GL_FALSE;
260 var->aux = NULL;
261 return 1;
262 }
263
264
265 void
266 slang_variable_destruct(slang_variable * var)
267 {
268 slang_fully_specified_type_destruct(&var->type);
269 if (var->initializer != NULL) {
270 slang_operation_destruct(var->initializer);
271 slang_alloc_free(var->initializer);
272 }
273 }
274
275
276 int
277 slang_variable_copy(slang_variable * x, const slang_variable * y)
278 {
279 slang_variable z;
280
281 if (!slang_variable_construct(&z))
282 return 0;
283 if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
284 slang_variable_destruct(&z);
285 return 0;
286 }
287 z.a_name = y->a_name;
288 z.array_len = y->array_len;
289 if (y->initializer != NULL) {
290 z.initializer
291 = (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
292 if (z.initializer == NULL) {
293 slang_variable_destruct(&z);
294 return 0;
295 }
296 if (!slang_operation_construct(z.initializer)) {
297 slang_alloc_free(z.initializer);
298 slang_variable_destruct(&z);
299 return 0;
300 }
301 if (!slang_operation_copy(z.initializer, y->initializer)) {
302 slang_variable_destruct(&z);
303 return 0;
304 }
305 }
306 z.address = y->address;
307 z.size = y->size;
308 slang_variable_destruct(x);
309 *x = z;
310 return 1;
311 }
312
313
314 slang_variable *
315 _slang_locate_variable(const slang_variable_scope * scope,
316 const slang_atom a_name, GLboolean all)
317 {
318 GLuint i;
319
320 for (i = 0; i < scope->num_variables; i++)
321 if (a_name == scope->variables[i]->a_name)
322 return scope->variables[i];
323 if (all && scope->outer_scope != NULL)
324 return _slang_locate_variable(scope->outer_scope, a_name, 1);
325 return NULL;
326 }
327
328 #if 0
329 static GLenum
330 gl_type_from_specifier(const slang_type_specifier * type)
331 {
332 switch (type->type) {
333 case SLANG_SPEC_BOOL:
334 return GL_BOOL_ARB;
335 case SLANG_SPEC_BVEC2:
336 return GL_BOOL_VEC2_ARB;
337 case SLANG_SPEC_BVEC3:
338 return GL_BOOL_VEC3_ARB;
339 case SLANG_SPEC_BVEC4:
340 return GL_BOOL_VEC4_ARB;
341 case SLANG_SPEC_INT:
342 return GL_INT;
343 case SLANG_SPEC_IVEC2:
344 return GL_INT_VEC2_ARB;
345 case SLANG_SPEC_IVEC3:
346 return GL_INT_VEC3_ARB;
347 case SLANG_SPEC_IVEC4:
348 return GL_INT_VEC4_ARB;
349 case SLANG_SPEC_FLOAT:
350 return GL_FLOAT;
351 case SLANG_SPEC_VEC2:
352 return GL_FLOAT_VEC2_ARB;
353 case SLANG_SPEC_VEC3:
354 return GL_FLOAT_VEC3_ARB;
355 case SLANG_SPEC_VEC4:
356 return GL_FLOAT_VEC4_ARB;
357 case SLANG_SPEC_MAT2:
358 return GL_FLOAT_MAT2_ARB;
359 case SLANG_SPEC_MAT3:
360 return GL_FLOAT_MAT3_ARB;
361 case SLANG_SPEC_MAT4:
362 return GL_FLOAT_MAT4_ARB;
363 case SLANG_SPEC_SAMPLER1D:
364 return GL_SAMPLER_1D_ARB;
365 case SLANG_SPEC_SAMPLER2D:
366 return GL_SAMPLER_2D_ARB;
367 case SLANG_SPEC_SAMPLER3D:
368 return GL_SAMPLER_3D_ARB;
369 case SLANG_SPEC_SAMPLERCUBE:
370 return GL_SAMPLER_CUBE_ARB;
371 case SLANG_SPEC_SAMPLER1DShadow:
372 return GL_SAMPLER_1D_SHADOW_ARB;
373 case SLANG_SPEC_SAMPLER2DShadow:
374 return GL_SAMPLER_2D_SHADOW_ARB;
375 case SLANG_SPEC_ARRAy:
376 return gl_type_from_specifier(type->_array);
377 default:
378 return GL_FLOAT;
379 }
380 }
381 #endif
382