2 #include "main/imports.h"
3 #include "shader/program.h"
4 #include "shader/prog_print.h"
5 #include "slang_compile.h"
6 #include "slang_compile_variable.h"
8 #include "slang_vartable.h"
23 * Variable/register info for one variable scope.
29 slang_variable
**Vars
; /* array [NumVars] */
31 TempState Temps
[MAX_PROGRAM_TEMPS
* 4]; /* per-component state */
32 int ValSize
[MAX_PROGRAM_TEMPS
* 4]; /**< For debug only */
34 struct table
*Parent
; /** Parent scope table */
39 * A variable table is a stack of tables, one per scope.
41 struct slang_var_table_
45 struct table
*Top
; /**< Table at top of stack */
51 _slang_new_var_table(GLuint maxRegisters
)
54 = (slang_var_table
*) _slang_alloc(sizeof(slang_var_table
));
56 vt
->MaxRegisters
= maxRegisters
;
63 _slang_delete_var_table(slang_var_table
*vt
)
66 _mesa_problem(NULL
, "non-empty var table in _slang_delete_var_table()");
75 * Create new table, put at head, return ptr to it.
76 * XXX we should take a maxTemps parameter to indicate how many temporaries
77 * are available for the current shader/program target.
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 * Destroy given table, return ptr to Parent
101 _slang_pop_var_table(slang_var_table
*vt
)
103 struct table
*t
= vt
->Top
;
106 if (dbg
) printf("Popping level %d\n", t
->Level
);
108 /* free the storage allocated for each variable */
109 for (i
= 0; i
< t
->NumVars
; i
++) {
110 slang_ir_storage
*store
= t
->Vars
[i
]->store
;
113 if (dbg
) printf(" Free var %s, size %d at %d.%s\n",
114 (char*) t
->Vars
[i
]->a_name
, store
->Size
,
116 _mesa_swizzle_string(store
->Swizzle
, 0, 0));
118 if (store
->File
== PROGRAM_SAMPLER
) {
119 /* samplers have no storage */
123 if (store
->Size
== 1)
124 comp
= GET_SWZ(store
->Swizzle
, 0);
128 assert(store
->Index
>= 0);
129 for (j
= 0; j
< store
->Size
; j
++) {
130 assert(t
->Temps
[store
->Index
* 4 + j
+ comp
] == VAR
);
131 t
->Temps
[store
->Index
* 4 + j
+ comp
] = FREE
;
136 /* just verify that any remaining allocations in this scope
139 for (i
= 0; i
< (int) vt
->MaxRegisters
* 4; i
++) {
140 if (t
->Temps
[i
] != FREE
&& t
->Parent
->Temps
[i
] == FREE
) {
141 if (dbg
) printf(" Free reg %d\n", i
/4);
142 assert(t
->Temps
[i
] == TEMP
);
148 _slang_free(t
->Vars
);
159 * Add a new variable to the given symbol table.
162 _slang_add_variable(slang_var_table
*vt
, slang_variable
*v
)
168 if (dbg
) printf("Adding var %s, store %p\n", (char *) v
->a_name
, (void *) v
->store
);
169 t
->Vars
= (slang_variable
**)
170 _slang_realloc(t
->Vars
,
171 t
->NumVars
* sizeof(slang_variable
*),
172 (t
->NumVars
+ 1) * sizeof(slang_variable
*));
173 t
->Vars
[t
->NumVars
] = v
;
179 * Look for variable by name in given table.
180 * If not found, Parent table will be searched.
183 _slang_find_variable(const slang_var_table
*vt
, slang_atom name
)
185 struct table
*t
= vt
->Top
;
188 for (i
= 0; i
< t
->NumVars
; i
++) {
189 if (t
->Vars
[i
]->a_name
== name
)
202 * \param size var size in floats
203 * \return position for var, measured in floats
206 alloc_reg(slang_var_table
*vt
, GLint size
, GLboolean isTemp
)
208 struct table
*t
= vt
->Top
;
209 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
210 const GLuint step
= (size
== 1) ? 1 : 4;
212 assert(size
> 0); /* number of floats */
214 for (i
= 0; i
<= vt
->MaxRegisters
* 4 - size
; i
+= step
) {
216 for (j
= 0; j
< (GLuint
) size
; j
++) {
217 if (i
+ j
< vt
->MaxRegisters
* 4 && t
->Temps
[i
+ j
] == FREE
) {
225 /* found block of size free regs */
228 for (j
= 0; j
< (GLuint
) size
; j
++)
229 t
->Temps
[i
+ j
] = isTemp
? TEMP
: VAR
;
230 assert(i
< MAX_PROGRAM_TEMPS
* 4);
231 t
->ValSize
[i
] = size
;
240 * Allocate temp register(s) for storing a variable.
241 * \param size size needed, in floats
242 * \param swizzle returns swizzle mask for accessing var in register
243 * \return register allocated, or -1
246 _slang_alloc_var(slang_var_table
*vt
, slang_ir_storage
*store
)
248 struct table
*t
= vt
->Top
;
251 if (store
->File
== PROGRAM_SAMPLER
) {
252 /* don't really allocate storage */
257 i
= alloc_reg(vt
, store
->Size
, GL_FALSE
);
261 store
->Index
= i
/ 4;
262 if (store
->Size
== 1) {
263 const GLuint comp
= i
% 4;
264 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
266 else if (store
->Size
== 2) {
267 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
268 SWIZZLE_NIL
, SWIZZLE_NIL
);
270 else if (store
->Size
== 3) {
271 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
272 SWIZZLE_Z
, SWIZZLE_NIL
);
275 store
->Swizzle
= SWIZZLE_NOOP
;
279 printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
280 store
->Size
, store
->Index
,
281 _mesa_swizzle_string(store
->Swizzle
, 0, 0),
291 * Allocate temp register(s) for storing an unnamed intermediate value.
294 _slang_alloc_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
296 struct table
*t
= vt
->Top
;
297 const int i
= alloc_reg(vt
, store
->Size
, GL_TRUE
);
301 assert(store
->Index
< 0);
303 store
->Index
= i
/ 4;
304 if (store
->Size
== 1) {
305 const GLuint comp
= i
% 4;
306 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
309 /* XXX improve swizzled for size=2/3, use for writemask... */
311 if (store
->Size
== 2) {
312 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
313 SWIZZLE_NIL
, SWIZZLE_NIL
);
316 store
->Swizzle
= SWIZZLE_NOOP
;
319 if (dbg
) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
320 store
->Size
, store
->Index
,
321 _mesa_swizzle_string(store
->Swizzle
, 0, 0), t
->Level
,
329 _slang_free_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
331 struct table
*t
= vt
->Top
;
333 GLuint r
= store
->Index
;
334 assert(store
->Size
> 0);
336 assert(r
+ store
->Size
<= vt
->MaxRegisters
* 4);
337 if (dbg
) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
339 _mesa_swizzle_string(store
->Swizzle
, 0, 0),
340 t
->Level
, (void *) store
);
341 if (store
->Size
== 1) {
342 const GLuint comp
= GET_SWZ(store
->Swizzle
, 0);
343 /* we can actually fail some of these assertions because of the
344 * troublesome IR_SWIZZLE handling.
347 assert(store
->Swizzle
== MAKE_SWIZZLE4(comp
, comp
, comp
, comp
));
349 assert(t
->ValSize
[r
* 4 + comp
] == 1);
351 assert(t
->Temps
[r
* 4 + comp
] == TEMP
);
352 t
->Temps
[r
* 4 + comp
] = FREE
;
355 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
356 assert(t
->ValSize
[r
*4] == store
->Size
);
357 for (i
= 0; i
< (GLuint
) store
->Size
; i
++) {
358 assert(t
->Temps
[r
* 4 + i
] == TEMP
);
359 t
->Temps
[r
* 4 + i
] = FREE
;
366 _slang_is_temp(const slang_var_table
*vt
, const slang_ir_storage
*store
)
368 struct table
*t
= vt
->Top
;
370 assert(store
->Index
>= 0);
371 assert(store
->Index
< (int) vt
->MaxRegisters
);
372 if (store
->Swizzle
== SWIZZLE_NOOP
)
375 comp
= GET_SWZ(store
->Swizzle
, 0);
377 if (t
->Temps
[store
->Index
* 4 + comp
] == TEMP
)