2 #include "main/imports.h"
3 #include "program/program.h"
4 #include "program/prog_print.h"
5 #include "slang_compile.h"
6 #include "slang_compile_variable.h"
7 #include "slang_emit.h"
9 #include "slang_vartable.h"
24 * Variable/register info for one variable scope.
30 slang_variable **Vars; /* array [NumVars] */
32 TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
33 int ValSize[MAX_PROGRAM_TEMPS * 4]; /**< For debug only */
35 struct table *Parent; /** Parent scope table */
40 * A variable table is a stack of tables, one per scope.
42 struct slang_var_table_
46 struct table *Top; /**< Table at top of stack */
52 _slang_new_var_table(GLuint maxRegisters)
55 = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
57 vt->MaxRegisters = maxRegisters;
64 _slang_delete_var_table(slang_var_table *vt)
67 _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
76 * Create new table on top of vartable stack.
77 * Used when we enter a {} block.
80 _slang_push_var_table(slang_var_table *vt)
82 struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
84 t->Level = vt->CurLevel++;
87 /* copy the info indicating which temp regs are in use */
88 memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
89 memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
92 if (dbg) printf("Pushing level %d\n", t->Level);
98 * Pop top entry from variable table.
99 * Used when we leave a {} block.
102 _slang_pop_var_table(slang_var_table *vt)
104 struct table *t = vt->Top;
107 if (dbg) printf("Popping level %d\n", t->Level);
109 /* free the storage allocated for each variable */
110 for (i = 0; i < t->NumVars; i++) {
111 slang_ir_storage *store = t->Vars[i]->store;
114 if (dbg) printf(" Free var %s, size %d at %d.%s\n",
115 (char*) t->Vars[i]->a_name, store->Size,
117 _mesa_swizzle_string(store->Swizzle, 0, 0));
119 if (store->File == PROGRAM_SAMPLER) {
120 /* samplers have no storage */
124 if (store->Size == 1)
125 comp = GET_SWZ(store->Swizzle, 0);
129 /* store->Index may be -1 if we run out of registers */
130 if (store->Index >= 0) {
131 for (j = 0; j < store->Size; j++) {
132 assert(t->Temps[store->Index * 4 + j + comp] == VAR);
133 t->Temps[store->Index * 4 + j + comp] = FREE;
139 /* just verify that any remaining allocations in this scope
142 for (i = 0; i < (int) vt->MaxRegisters * 4; i++) {
143 if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
144 if (dbg) printf(" Free reg %d\n", i/4);
145 assert(t->Temps[i] == TEMP);
151 _slang_free(t->Vars);
162 * Add a new variable to the given var/symbol table.
165 _slang_add_variable(slang_var_table *vt, slang_variable *v)
171 if (dbg) printf("Adding var %s, store %p\n", (char *) v->a_name, (void *) v->store);
172 t->Vars = (slang_variable **)
173 _slang_realloc(t->Vars,
174 t->NumVars * sizeof(slang_variable *),
175 (t->NumVars + 1) * sizeof(slang_variable *));
176 t->Vars[t->NumVars] = v;
182 * Look for variable by name in given table.
183 * If not found, Parent table will be searched.
186 _slang_find_variable(const slang_var_table *vt, slang_atom name)
188 struct table *t = vt->Top;
191 for (i = 0; i < t->NumVars; i++) {
192 if (t->Vars[i]->a_name == name)
205 * \param size var size in floats
206 * \return position for var, measured in floats
209 alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
211 struct table *t = vt->Top;
212 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
213 const GLuint step = (size == 1) ? 1 : 4;
215 assert(size > 0); /* number of floats */
217 for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
219 for (j = 0; j < (GLuint) size; j++) {
220 assert(i + j < 4 * MAX_PROGRAM_TEMPS);
221 if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
229 /* found block of size free regs */
232 for (j = 0; j < (GLuint) size; j++) {
233 assert(i + j < 4 * MAX_PROGRAM_TEMPS);
234 t->Temps[i + j] = isTemp ? TEMP : VAR;
236 assert(i < MAX_PROGRAM_TEMPS * 4);
237 t->ValSize[i] = size;
242 /* if we get here, we ran out of registers */
248 * Allocate temp register(s) for storing a variable.
249 * \param size size needed, in floats
250 * \param swizzle returns swizzle mask for accessing var in register
251 * \return register allocated, or -1
254 _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
256 struct table *t = vt->Top;
259 if (store->File == PROGRAM_SAMPLER) {
260 /* don't really allocate storage */
265 i = alloc_reg(vt, store->Size, GL_FALSE);
269 store->Index = i / 4;
270 store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
273 printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
274 store->Size, store->Index,
275 _mesa_swizzle_string(store->Swizzle, 0, 0),
285 * Allocate temp register(s) for storing an unnamed intermediate value.
288 _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
290 struct table *t = vt->Top;
291 const int i = alloc_reg(vt, store->Size, GL_TRUE);
295 assert(store->Index < 0);
297 store->Index = i / 4;
298 store->Swizzle = _slang_var_swizzle(store->Size, i % 4);
300 if (dbg) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
301 store->Size, store->Index,
302 _mesa_swizzle_string(store->Swizzle, 0, 0), t->Level,
310 _slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
312 struct table *t = vt->Top;
314 GLint r = store->Index;
315 assert(store->Size > 0);
317 assert((GLuint)r + store->Size <= vt->MaxRegisters * 4);
318 if (dbg) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
320 _mesa_swizzle_string(store->Swizzle, 0, 0),
321 t->Level, (void *) store);
322 if (store->Size == 1) {
323 const GLuint comp = GET_SWZ(store->Swizzle, 0);
324 /* we can actually fail some of these assertions because of the
325 * troublesome IR_SWIZZLE handling.
328 assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
330 assert(t->ValSize[r * 4 + comp] == 1);
332 assert(t->Temps[r * 4 + comp] == TEMP);
333 t->Temps[r * 4 + comp] = FREE;
336 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
337 assert(t->ValSize[r*4] == store->Size);
338 for (i = 0; i < (GLuint) store->Size; i++) {
339 assert(t->Temps[r * 4 + i] == TEMP);
340 t->Temps[r * 4 + i] = FREE;
347 _slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
349 struct table *t = vt->Top;
351 assert(store->Index >= 0);
352 assert(store->Index < (int) vt->MaxRegisters);
353 if (store->Swizzle == SWIZZLE_NOOP)
356 comp = GET_SWZ(store->Swizzle, 0);
358 if (t->Temps[store->Index * 4 + comp] == TEMP)