remove bogus assertion
[mesa.git] / src / mesa / shader / slang / slang_vartable.c
1
2 #include "imports.h"
3 #include "slang_compile.h"
4 #include "slang_compile_variable.h"
5 #include "slang_vartable.h"
6 #include "slang_ir.h"
7 #include "prog_instruction.h"
8
9
10 static int dbg = 0;
11
12
13 typedef enum {
14 FREE,
15 VAR,
16 TEMP
17 } TempState;
18
19
20 /**
21 * Variable/register info for one variable scope.
22 */
23 struct table
24 {
25 int Level;
26 int NumVars;
27 slang_variable **Vars; /* array [NumVars] */
28
29 TempState Temps[MAX_PROGRAM_TEMPS * 4]; /* per-component state */
30 int ValSize[MAX_PROGRAM_TEMPS]; /* For debug only */
31
32 struct table *Parent; /** Parent scope table */
33 };
34
35
36 /**
37 * A variable table is a stack of tables, one per scope.
38 */
39 struct slang_var_table_
40 {
41 GLint CurLevel;
42 GLuint MaxRegisters;
43 struct table *Top; /**< Table at top of stack */
44 };
45
46
47
48 slang_var_table *
49 _slang_new_var_table(GLuint maxRegisters)
50 {
51 slang_var_table *vt
52 = (slang_var_table *) _mesa_calloc(sizeof(slang_var_table));
53 if (vt) {
54 vt->MaxRegisters = maxRegisters;
55 }
56 return vt;
57 }
58
59
60 void
61 _slang_delete_var_table(slang_var_table *vt)
62 {
63 if (vt->Top) {
64 _mesa_problem(NULL, "non-empty var table in _slang_delete_var_table()");
65 return;
66 }
67 _mesa_free(vt);
68 }
69
70
71
72 /**
73 * Create new table, put at head, return ptr to it.
74 * XXX we should take a maxTemps parameter to indicate how many temporaries
75 * are available for the current shader/program target.
76 */
77 void
78 _slang_push_var_table(slang_var_table *vt)
79 {
80 struct table *t = (struct table *) _mesa_calloc(sizeof(struct table));
81 if (t) {
82 t->Level = vt->CurLevel++;
83 t->Parent = vt->Top;
84 if (t->Parent) {
85 /* copy the info indicating which temp regs are in use */
86 memcpy(t->Temps, t->Parent->Temps, sizeof(t->Temps));
87 memcpy(t->ValSize, t->Parent->ValSize, sizeof(t->ValSize));
88 }
89 vt->Top = t;
90 if (dbg) printf("Pushing level %d\n", t->Level);
91 }
92 }
93
94
95 /**
96 * Destroy given table, return ptr to Parent
97 */
98 void
99 _slang_pop_var_table(slang_var_table *vt)
100 {
101 struct table *t = vt->Top;
102 int i;
103
104 if (dbg) printf("Popping level %d\n", t->Level);
105
106 /* free the storage allocated for each variable */
107 for (i = 0; i < t->NumVars; i++) {
108 slang_ir_storage *store = (slang_ir_storage *) t->Vars[i]->aux;
109 GLint j;
110 GLuint comp;
111 if (dbg) printf(" Free var %s, size %d at %d\n",
112 (char*) t->Vars[i]->a_name, store->Size,
113 store->Index);
114
115 if (store->Size == 1)
116 comp = GET_SWZ(store->Swizzle, 0);
117 else
118 comp = 0;
119
120 assert(store->Index >= 0);
121 for (j = 0; j < store->Size; j++) {
122 assert(t->Temps[store->Index * 4 + j + comp] == VAR);
123 t->Temps[store->Index * 4 + j + comp] = FREE;
124 }
125 store->Index = -1;
126 }
127 if (t->Parent) {
128 /* just verify that any remaining allocations in this scope
129 * were for temps
130 */
131 for (i = 0; i < vt->MaxRegisters * 4; i++) {
132 if (t->Temps[i] != FREE && t->Parent->Temps[i] == FREE) {
133 if (dbg) printf(" Free reg %d\n", i/4);
134 assert(t->Temps[i] == TEMP);
135 }
136 }
137 }
138
139 if (t->Vars)
140 free(t->Vars);
141
142 vt->Top = t->Parent;
143 free(t);
144 vt->CurLevel--;
145 }
146
147
148 /**
149 * Add a new variable to the given symbol table.
150 */
151 void
152 _slang_add_variable(slang_var_table *vt, slang_variable *v)
153 {
154 struct table *t;
155 assert(vt);
156 t = vt->Top;
157 assert(t);
158 if (dbg) printf("Adding var %s\n", (char *) v->a_name);
159 t->Vars = realloc(t->Vars, (t->NumVars + 1) * sizeof(slang_variable *));
160 t->Vars[t->NumVars] = v;
161 t->NumVars++;
162 }
163
164
165 /**
166 * Look for variable by name in given table.
167 * If not found, Parent table will be searched.
168 */
169 slang_variable *
170 _slang_find_variable(const slang_var_table *vt, slang_atom name)
171 {
172 struct table *t = vt->Top;
173 while (1) {
174 int i;
175 for (i = 0; i < t->NumVars; i++) {
176 if (t->Vars[i]->a_name == name)
177 return t->Vars[i];
178 }
179 if (t->Parent)
180 t = t->Parent;
181 else
182 return NULL;
183 }
184 }
185
186
187 /**
188 * Allocation helper.
189 * \param size var size in floats
190 * \return position for var, measured in floats
191 */
192 static GLint
193 alloc_reg(slang_var_table *vt, GLint size, GLboolean isTemp)
194 {
195 struct table *t = vt->Top;
196 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
197 const GLuint step = (size == 1) ? 1 : 4;
198 GLuint i, j;
199 assert(size > 0); /* number of floats */
200
201 for (i = 0; i <= vt->MaxRegisters * 4 - size; i += step) {
202 GLuint found = 0;
203 for (j = 0; j < size; j++) {
204 if (i + j < vt->MaxRegisters * 4 && t->Temps[i + j] == FREE) {
205 found++;
206 }
207 else {
208 break;
209 }
210 }
211 if (found == size) {
212 /* found block of size free regs */
213 if (size > 1)
214 assert(i % 4 == 0);
215 for (j = 0; j < size; j++)
216 t->Temps[i + j] = isTemp ? TEMP : VAR;
217 t->ValSize[i] = size;
218 return i;
219 }
220 }
221 return -1;
222 }
223
224
225 /**
226 * Allocate temp register(s) for storing a variable.
227 * \param size size needed, in floats
228 * \param swizzle returns swizzle mask for accessing var in register
229 * \return register allocated, or -1
230 */
231 GLboolean
232 _slang_alloc_var(slang_var_table *vt, slang_ir_storage *store)
233 {
234 struct table *t = vt->Top;
235 const int i = alloc_reg(vt, store->Size, GL_FALSE);
236 if (i < 0)
237 return GL_FALSE;
238
239 store->Index = i / 4;
240 if (store->Size == 1) {
241 const GLuint comp = i % 4;
242 store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
243 if (dbg) printf("Alloc var sz %d at %d.%c (level %d)\n",
244 store->Size, store->Index, "xyzw"[comp], t->Level);
245 }
246 else {
247 store->Swizzle = SWIZZLE_NOOP;
248 if (dbg) printf("Alloc var sz %d at %d.xyzw (level %d)\n",
249 store->Size, store->Index, t->Level);
250 }
251 return GL_TRUE;
252 }
253
254
255
256 /**
257 * Allocate temp register(s) for storing an unnamed intermediate value.
258 */
259 GLboolean
260 _slang_alloc_temp(slang_var_table *vt, slang_ir_storage *store)
261 {
262 struct table *t = vt->Top;
263 const int i = alloc_reg(vt, store->Size, GL_TRUE);
264 if (i < 0)
265 return GL_FALSE;
266
267 store->Index = i / 4;
268 if (store->Size == 1) {
269 const GLuint comp = i % 4;
270 store->Swizzle = MAKE_SWIZZLE4(comp, comp, comp, comp);
271 if (dbg) printf("Alloc temp sz %d at %d.%c (level %d)\n",
272 store->Size, store->Index, "xyzw"[comp], t->Level);
273 }
274 else {
275 store->Swizzle = SWIZZLE_NOOP;
276 if (dbg) printf("Alloc temp sz %d at %d.xyzw (level %d)\n",
277 store->Size, store->Index, t->Level);
278 }
279 return GL_TRUE;
280 }
281
282
283 void
284 _slang_free_temp(slang_var_table *vt, slang_ir_storage *store)
285 {
286 struct table *t = vt->Top;
287 GLuint i;
288 GLuint r = store->Index;
289 assert(store->Size > 0);
290 assert(r >= 0);
291 assert(r + store->Size <= vt->MaxRegisters * 4);
292 if (dbg) printf("Free temp sz %d at %d (level %d)\n", store->Size, r, t->Level);
293 if (store->Size == 1) {
294 const GLuint comp = GET_SWZ(store->Swizzle, 0);
295 assert(store->Swizzle == MAKE_SWIZZLE4(comp, comp, comp, comp));
296 assert(comp < 4);
297 assert(t->ValSize[r * 4 + comp] == 1);
298 assert(t->Temps[r * 4 + comp] == TEMP);
299 t->Temps[r * 4 + comp] = FREE;
300 }
301 else {
302 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
303 assert(t->ValSize[r*4] == store->Size);
304 for (i = 0; i < store->Size; i++) {
305 assert(t->Temps[r * 4 + i] == TEMP);
306 t->Temps[r * 4 + i] = FREE;
307 }
308 }
309 }
310
311
312 GLboolean
313 _slang_is_temp(const slang_var_table *vt, const slang_ir_storage *store)
314 {
315 struct table *t = vt->Top;
316 assert(store->Index >= 0);
317 assert(store->Index < vt->MaxRegisters);
318 GLuint comp;
319 if (store->Swizzle == SWIZZLE_NOOP)
320 comp = 0;
321 else
322 comp = GET_SWZ(store->Swizzle, 0);
323
324 if (t->Temps[store->Index * 4 + comp] == TEMP)
325 return GL_TRUE;
326 else
327 return GL_FALSE;
328 }