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"
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 GLuint r
= store
->Index
;
315 assert(store
->Size
> 0);
317 assert(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
)