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)