chmod a-x
[mesa.git] / src / mesa / shader / slang / slang_compile_variable.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_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 * slang_variable_scope
128 */
129
130 slang_variable_scope *
131 _slang_variable_scope_new(slang_variable_scope *parent)
132 {
133 slang_variable_scope *s;
134 s = (slang_variable_scope *) _mesa_calloc(sizeof(slang_variable_scope));
135 s->outer_scope = parent;
136 return s;
137 }
138
139
140 GLvoid
141 _slang_variable_scope_ctr(slang_variable_scope * self)
142 {
143 self->variables = NULL;
144 self->num_variables = 0;
145 self->outer_scope = NULL;
146 }
147
148 void
149 slang_variable_scope_destruct(slang_variable_scope * scope)
150 {
151 unsigned int i;
152
153 if (!scope)
154 return;
155 for (i = 0; i < scope->num_variables; i++)
156 slang_variable_destruct(scope->variables + i);
157 slang_alloc_free(scope->variables);
158 /* do not free scope->outer_scope */
159 }
160
161 int
162 slang_variable_scope_copy(slang_variable_scope * x,
163 const slang_variable_scope * y)
164 {
165 slang_variable_scope z;
166 unsigned int i;
167
168 _slang_variable_scope_ctr(&z);
169 z.variables = (slang_variable *)
170 slang_alloc_malloc(y->num_variables * sizeof(slang_variable));
171 if (z.variables == NULL) {
172 slang_variable_scope_destruct(&z);
173 return 0;
174 }
175 for (z.num_variables = 0; z.num_variables < y->num_variables;
176 z.num_variables++) {
177 if (!slang_variable_construct(&z.variables[z.num_variables])) {
178 slang_variable_scope_destruct(&z);
179 return 0;
180 }
181 }
182 for (i = 0; i < z.num_variables; i++) {
183 if (!slang_variable_copy(&z.variables[i], &y->variables[i])) {
184 slang_variable_scope_destruct(&z);
185 return 0;
186 }
187 }
188 z.outer_scope = y->outer_scope;
189 slang_variable_scope_destruct(x);
190 *x = z;
191 return 1;
192 }
193
194
195 /**
196 * Grow the variable list by one.
197 * \return pointer to space for the new variable (will be initialized)
198 */
199 slang_variable *
200 slang_variable_scope_grow(slang_variable_scope *scope)
201 {
202 const int n = scope->num_variables;
203 scope->variables = (slang_variable *)
204 slang_alloc_realloc(scope->variables,
205 n * sizeof(slang_variable),
206 (n + 1) * sizeof(slang_variable));
207 if (!scope->variables)
208 return NULL;
209
210 scope->num_variables++;
211
212 if (!slang_variable_construct(scope->variables + n))
213 return NULL;
214
215 return scope->variables + n;
216 }
217
218
219
220 /* slang_variable */
221
222 int
223 slang_variable_construct(slang_variable * var)
224 {
225 if (!slang_fully_specified_type_construct(&var->type))
226 return 0;
227 var->a_name = SLANG_ATOM_NULL;
228 var->array_len = 0;
229 var->initializer = NULL;
230 var->address = ~0;
231 var->size = 0;
232 var->global = GL_FALSE;
233 var->declared = GL_FALSE;
234 var->used = GL_FALSE;
235 var->aux = NULL;
236 return 1;
237 }
238
239 void
240 slang_variable_destruct(slang_variable * var)
241 {
242 slang_fully_specified_type_destruct(&var->type);
243 if (var->initializer != NULL) {
244 slang_operation_destruct(var->initializer);
245 slang_alloc_free(var->initializer);
246 }
247 }
248
249 int
250 slang_variable_copy(slang_variable * x, const slang_variable * y)
251 {
252 slang_variable z;
253
254 if (!slang_variable_construct(&z))
255 return 0;
256 if (!slang_fully_specified_type_copy(&z.type, &y->type)) {
257 slang_variable_destruct(&z);
258 return 0;
259 }
260 z.a_name = y->a_name;
261 z.array_len = y->array_len;
262 if (y->initializer != NULL) {
263 z.initializer
264 = (slang_operation *) slang_alloc_malloc(sizeof(slang_operation));
265 if (z.initializer == NULL) {
266 slang_variable_destruct(&z);
267 return 0;
268 }
269 if (!slang_operation_construct(z.initializer)) {
270 slang_alloc_free(z.initializer);
271 slang_variable_destruct(&z);
272 return 0;
273 }
274 if (!slang_operation_copy(z.initializer, y->initializer)) {
275 slang_variable_destruct(&z);
276 return 0;
277 }
278 }
279 z.address = y->address;
280 z.size = y->size;
281 z.global = y->global;
282 slang_variable_destruct(x);
283 *x = z;
284 return 1;
285 }
286
287 slang_variable *
288 _slang_locate_variable(const slang_variable_scope * scope,
289 const slang_atom a_name, GLboolean all)
290 {
291 GLuint i;
292
293 for (i = 0; i < scope->num_variables; i++)
294 if (a_name == scope->variables[i].a_name)
295 return &scope->variables[i];
296 if (all && scope->outer_scope != NULL)
297 return _slang_locate_variable(scope->outer_scope, a_name, 1);
298 return NULL;
299 }
300
301 /*
302 * _slang_build_export_data_table()
303 */
304
305 static GLenum
306 gl_type_from_specifier(const slang_type_specifier * type)
307 {
308 switch (type->type) {
309 case slang_spec_bool:
310 return GL_BOOL_ARB;
311 case slang_spec_bvec2:
312 return GL_BOOL_VEC2_ARB;
313 case slang_spec_bvec3:
314 return GL_BOOL_VEC3_ARB;
315 case slang_spec_bvec4:
316 return GL_BOOL_VEC4_ARB;
317 case slang_spec_int:
318 return GL_INT;
319 case slang_spec_ivec2:
320 return GL_INT_VEC2_ARB;
321 case slang_spec_ivec3:
322 return GL_INT_VEC3_ARB;
323 case slang_spec_ivec4:
324 return GL_INT_VEC4_ARB;
325 case slang_spec_float:
326 return GL_FLOAT;
327 case slang_spec_vec2:
328 return GL_FLOAT_VEC2_ARB;
329 case slang_spec_vec3:
330 return GL_FLOAT_VEC3_ARB;
331 case slang_spec_vec4:
332 return GL_FLOAT_VEC4_ARB;
333 case slang_spec_mat2:
334 return GL_FLOAT_MAT2_ARB;
335 case slang_spec_mat3:
336 return GL_FLOAT_MAT3_ARB;
337 case slang_spec_mat4:
338 return GL_FLOAT_MAT4_ARB;
339 case slang_spec_sampler1D:
340 return GL_SAMPLER_1D_ARB;
341 case slang_spec_sampler2D:
342 return GL_SAMPLER_2D_ARB;
343 case slang_spec_sampler3D:
344 return GL_SAMPLER_3D_ARB;
345 case slang_spec_samplerCube:
346 return GL_SAMPLER_CUBE_ARB;
347 case slang_spec_sampler1DShadow:
348 return GL_SAMPLER_1D_SHADOW_ARB;
349 case slang_spec_sampler2DShadow:
350 return GL_SAMPLER_2D_SHADOW_ARB;
351 case slang_spec_array:
352 return gl_type_from_specifier(type->_array);
353 default:
354 return GL_FLOAT;
355 }
356 }
357
358 static GLboolean
359 build_quant(slang_export_data_quant * q, const slang_variable * var)
360 {
361 const slang_type_specifier *spec = &var->type.specifier;
362
363 q->name = var->a_name;
364 q->size = var->size;
365 if (spec->type == slang_spec_array) {
366 q->array_len = var->array_len;
367 q->size /= var->array_len;
368 spec = spec->_array;
369 }
370 if (spec->type == slang_spec_struct) {
371 GLuint i;
372
373 q->u.field_count = spec->_struct->fields->num_variables;
374 q->structure = (slang_export_data_quant *)
375 slang_alloc_malloc(q->u.field_count
376 * sizeof(slang_export_data_quant));
377 if (q->structure == NULL)
378 return GL_FALSE;
379
380 for (i = 0; i < q->u.field_count; i++)
381 slang_export_data_quant_ctr(&q->structure[i]);
382 for (i = 0; i < q->u.field_count; i++) {
383 if (!build_quant(&q->structure[i],
384 &spec->_struct->fields->variables[i]))
385 return GL_FALSE;
386 }
387 }
388 else
389 q->u.basic_type = gl_type_from_specifier(spec);
390 return GL_TRUE;
391 }
392
393 GLboolean
394 _slang_build_export_data_table(slang_export_data_table * tbl,
395 slang_variable_scope * vars)
396 {
397 GLuint i;
398
399 for (i = 0; i < vars->num_variables; i++) {
400 const slang_variable *var = &vars->variables[i];
401 slang_export_data_entry *e;
402
403 e = slang_export_data_table_add(tbl);
404 if (e == NULL)
405 return GL_FALSE;
406 if (!build_quant(&e->quant, var))
407 return GL_FALSE;
408 if (var->type.qualifier == slang_qual_uniform)
409 e->access = slang_exp_uniform;
410 else if (var->type.qualifier == slang_qual_attribute)
411 e->access = slang_exp_attribute;
412 else
413 e->access = slang_exp_varying;
414 e->address = var->address;
415 }
416
417 if (vars->outer_scope != NULL)
418 return _slang_build_export_data_table(tbl, vars->outer_scope);
419 return GL_TRUE;
420 }