3 #include "slang_compile.h"
4 #include "slang_compile_variable.h"
6 #include "slang_vartable.h"
8 #include "prog_instruction.h"
22 * Variable/register info for one variable scope.
28 slang_variable **Vars; /* array [NumVars] */
30 TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
31 int ValSize[MAX_PROGRAM_TEMPS]; /* For debug only */
33 struct table *Parent; /** Parent scope table */
38 * A variable table is a stack of tables, one per scope.
40 struct slang_var_table_
44 struct table *Top; /**< Table at top of stack */
50 _slang_new_var_table(GLuint maxRegisters)
53 = (slang_var_table *) _slang_alloc(sizeof(slang_var_table));
55 vt->MaxRegisters = maxRegisters;
62 _slang_delete_var_table(slang_var_table *vt)
65 _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
74 * Create new table, put at head, return ptr to it.
75 * XXX we should take a maxTemps parameter to indicate how many temporaries
76 * are available for the current shader/program target.
79 _slang_push_var_table(slang_var_table *vt)
81 struct table *t = (struct table *) _slang_alloc(sizeof(struct table));
83 t->Level = vt->CurLevel++;
86 /* copy the info indicating which temp regs are in use */
87 memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
88 memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
91 if (dbg) printf("Pushing level %d\n", t->Level);
97 * Destroy given table, return ptr to Parent
100 _slang_pop_var_table(slang_var_table *vt)
102 struct table *t = vt->Top;
105 if (dbg) printf("Popping level %d\n", t->Level);
107 /* free the storage allocated for each variable */
108 for (i = 0; i < t->NumVars; i++) {
109 slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux;
112 if (dbg) printf(" Free var %s, size %d at %d\n",
113 (char*) t->Vars[i]->a_name, store->Size,
116 if (store->Size == 1)
117 comp = GET_SWZ(store->Swizzle, 0);
121 assert(store->Index >= 0);
122 for (j = 0; j < store->Size; j++) {
123 assert(t->Temps[store->Index * 4 + j + comp] == VAR);
124 t->Temps[store->Index * 4 + j + comp] = FREE;
129 /* just verify that any remaining allocations in this scope
132 for (i = 0; i < vt->MaxRegisters * 4; i++) {
133 if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
134 if (dbg) printf(" Free reg %d\n", i/4);
135 assert(t->Temps[i] == TEMP);
141 _slang_free(t->Vars);
152 * Add a new variable to the given symbol table.
155 _slang_add_variable(slang_var_table *vt, slang_variable *v)
161 if (dbg) printf("Adding var %s\n", (char *) v->a_name);
162 t->Vars = (slang_variable **)
163 _slang_realloc(t->Vars,
164 t->NumVars * sizeof(slang_variable *),
165 (t->NumVars + 1) * sizeof(slang_variable *));
166 t->Vars[t->NumVars] = v;
172 * Look for variable by name in given table.
173 * If not found, Parent table will be searched.
176 _slang_find_variable(const slang_var_table *vt, slang_atom name)
178 struct table *t = vt->Top;
181 for (i = 0; i < t->NumVars; i++) {
182 if (t->Vars[i]->a_name == name)
195 * \param size var size in floats
196 * \return position for var, measured in floats
199 alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
201 struct table *t = vt->Top;
202 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
203 const GLuint step = (size == 1) ? 1 : 4;
205 assert(size > 0); /* number of floats */
207 for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
209 for (j = 0; j < size; j++) {
210 if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
218 /* found block of size free regs */
221 for (j = 0; j < size; j++)
222 t->Temps[i + j] = isTemp ? TEMP : VAR;
223 t->ValSize[i] = size;
232 * Allocate temp register(s) for storing a variable.
233 * \param size size needed, in floats
234 * \param swizzle returns swizzle mask for accessing var in register
235 * \return register allocated, or -1
238 _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
240 struct table *t = vt->Top;
241 const int i = alloc_reg(vt, store->Size, GL_FALSE);
245 store->Index = i / 4;
246 if (store->Size == 1) {
247 const GLuint comp = i % 4;
248 store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
249 if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n",
250 store->Size, store->Index, "xyzw"[comp], t->Level);
253 store->Swizzle = SWIZZLE_NOOP;
254 if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
255 store->Size, store->Index, t->Level);
263 * Allocate temp register(s) for storing an unnamed intermediate value.
266 _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
268 struct table *t = vt->Top;
269 const int i = alloc_reg(vt, store->Size, GL_TRUE);
273 store->Index = i / 4;
274 if (store->Size == 1) {
275 const GLuint comp = i % 4;
276 store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
277 if (dbg) printf("Alloc temp sz %d at %d.%c (level %d)\n",
278 store->Size, store->Index, "xyzw"[comp], t->Level);
281 store->Swizzle = SWIZZLE_NOOP;
282 if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
283 store->Size, store->Index, t->Level);
290 _slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
292 struct table *t = vt->Top;
294 GLuint r = store->Index;
295 assert(store->Size > 0);
297 assert(r + store->Size <= vt->MaxRegisters * 4);
298 if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level);
299 if (store->Size == 1) {
300 const GLuint comp = GET_SWZ(store->Swizzle, 0);
301 assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
303 assert(t->ValSize[r * 4 + comp] == 1);
304 assert(t->Temps[r * 4 + comp] == TEMP);
305 t->Temps[r * 4 + comp] = FREE;
308 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
309 assert(t->ValSize[r*4] == store->Size);
310 for (i = 0; i < store->Size; i++) {
311 assert(t->Temps[r * 4 + i] == TEMP);
312 t->Temps[r * 4 + i] = FREE;
319 _slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
321 struct table *t = vt->Top;
323 assert(store->Index >= 0);
324 assert(store->Index < vt->MaxRegisters);
325 if (store->Swizzle == SWIZZLE_NOOP)
328 comp = GET_SWZ(store->Swizzle, 0);
330 if (t->Temps[store->Index * 4 + comp] == TEMP)