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
= (slang_ir_storage
*) t
->Vars
[i
]->aux
;
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
->Size
== 1)
119 comp
= GET_SWZ(store
->Swizzle
, 0);
123 assert(store
->Index
>= 0);
124 for (j
= 0; j
< store
->Size
; j
++) {
125 assert(t
->Temps
[store
->Index
* 4 + j
+ comp
] == VAR
);
126 t
->Temps
[store
->Index
* 4 + j
+ comp
] = FREE
;
131 /* just verify that any remaining allocations in this scope
134 for (i
= 0; i
< (int) vt
->MaxRegisters
* 4; i
++) {
135 if (t
->Temps
[i
] != FREE
&& t
->Parent
->Temps
[i
] == FREE
) {
136 if (dbg
) printf(" Free reg %d\n", i
/4);
137 assert(t
->Temps
[i
] == TEMP
);
143 _slang_free(t
->Vars
);
154 * Add a new variable to the given symbol table.
157 _slang_add_variable(slang_var_table
*vt
, slang_variable
*v
)
163 if (dbg
) printf("Adding var %s, store %p\n", (char *) v
->a_name
, v
->aux
);
164 t
->Vars
= (slang_variable
**)
165 _slang_realloc(t
->Vars
,
166 t
->NumVars
* sizeof(slang_variable
*),
167 (t
->NumVars
+ 1) * sizeof(slang_variable
*));
168 t
->Vars
[t
->NumVars
] = v
;
174 * Look for variable by name in given table.
175 * If not found, Parent table will be searched.
178 _slang_find_variable(const slang_var_table
*vt
, slang_atom name
)
180 struct table
*t
= vt
->Top
;
183 for (i
= 0; i
< t
->NumVars
; i
++) {
184 if (t
->Vars
[i
]->a_name
== name
)
197 * \param size var size in floats
198 * \return position for var, measured in floats
201 alloc_reg(slang_var_table
*vt
, GLint size
, GLboolean isTemp
)
203 struct table
*t
= vt
->Top
;
204 /* if size == 1, allocate anywhere, else, pos must be multiple of 4 */
205 const GLuint step
= (size
== 1) ? 1 : 4;
207 assert(size
> 0); /* number of floats */
209 for (i
= 0; i
<= vt
->MaxRegisters
* 4 - size
; i
+= step
) {
211 for (j
= 0; j
< (GLuint
) size
; j
++) {
212 if (i
+ j
< vt
->MaxRegisters
* 4 && t
->Temps
[i
+ j
] == FREE
) {
220 /* found block of size free regs */
223 for (j
= 0; j
< (GLuint
) size
; j
++)
224 t
->Temps
[i
+ j
] = isTemp
? TEMP
: VAR
;
225 assert(i
< MAX_PROGRAM_TEMPS
* 4);
226 t
->ValSize
[i
] = size
;
235 * Allocate temp register(s) for storing a variable.
236 * \param size size needed, in floats
237 * \param swizzle returns swizzle mask for accessing var in register
238 * \return register allocated, or -1
241 _slang_alloc_var(slang_var_table
*vt
, slang_ir_storage
*store
)
243 struct table
*t
= vt
->Top
;
244 const int i
= alloc_reg(vt
, store
->Size
, GL_FALSE
);
248 store
->Index
= i
/ 4;
249 if (store
->Size
== 1) {
250 const GLuint comp
= i
% 4;
251 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
253 else if (store
->Size
== 2) {
254 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
255 SWIZZLE_NIL
, SWIZZLE_NIL
);
257 else if (store
->Size
== 3) {
258 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
259 SWIZZLE_Z
, SWIZZLE_NIL
);
262 store
->Swizzle
= SWIZZLE_NOOP
;
266 printf("Alloc var storage sz %d at %d.%s (level %d) store %p\n",
267 store
->Size
, store
->Index
,
268 _mesa_swizzle_string(store
->Swizzle
, 0, 0),
278 * Allocate temp register(s) for storing an unnamed intermediate value.
281 _slang_alloc_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
283 struct table
*t
= vt
->Top
;
284 const int i
= alloc_reg(vt
, store
->Size
, GL_TRUE
);
288 assert(store
->Index
< 0);
290 store
->Index
= i
/ 4;
291 if (store
->Size
== 1) {
292 const GLuint comp
= i
% 4;
293 store
->Swizzle
= MAKE_SWIZZLE4(comp
, comp
, comp
, comp
);
296 /* XXX improve swizzled for size=2/3, use for writemask... */
298 if (store
->Size
== 2) {
299 store
->Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
,
300 SWIZZLE_NIL
, SWIZZLE_NIL
);
303 store
->Swizzle
= SWIZZLE_NOOP
;
306 if (dbg
) printf("Alloc temp sz %d at %d.%s (level %d) store %p\n",
307 store
->Size
, store
->Index
,
308 _mesa_swizzle_string(store
->Swizzle
, 0, 0), t
->Level
,
316 _slang_free_temp(slang_var_table
*vt
, slang_ir_storage
*store
)
318 struct table
*t
= vt
->Top
;
320 GLuint r
= store
->Index
;
321 assert(store
->Size
> 0);
323 assert(r
+ store
->Size
<= vt
->MaxRegisters
* 4);
324 if (dbg
) printf("Free temp sz %d at %d.%s (level %d) store %p\n",
326 _mesa_swizzle_string(store
->Swizzle
, 0, 0),
327 t
->Level
, (void *) store
);
328 if (store
->Size
== 1) {
329 const GLuint comp
= GET_SWZ(store
->Swizzle
, 0);
330 /* we can actually fail some of these assertions because of the
331 * troublesome IR_SWIZZLE handling.
334 assert(store
->Swizzle
== MAKE_SWIZZLE4(comp
, comp
, comp
, comp
));
336 assert(t
->ValSize
[r
* 4 + comp
] == 1);
338 assert(t
->Temps
[r
* 4 + comp
] == TEMP
);
339 t
->Temps
[r
* 4 + comp
] = FREE
;
342 /*assert(store->Swizzle == SWIZZLE_NOOP);*/
343 assert(t
->ValSize
[r
*4] == store
->Size
);
344 for (i
= 0; i
< (GLuint
) store
->Size
; i
++) {
345 assert(t
->Temps
[r
* 4 + i
] == TEMP
);
346 t
->Temps
[r
* 4 + i
] = FREE
;
353 _slang_is_temp(const slang_var_table
*vt
, const slang_ir_storage
*store
)
355 struct table
*t
= vt
->Top
;
357 assert(store
->Index
>= 0);
358 assert(store
->Index
< (int) vt
->MaxRegisters
);
359 if (store
->Swizzle
== SWIZZLE_NOOP
)
362 comp
= GET_SWZ(store
->Swizzle
, 0);
364 if (t
->Temps
[store
->Index
* 4 + comp
] == TEMP
)